noip2018信心赛day2 死亡如风(trie)

3.死亡如风

Description
hjw与yqw被空投到一个叫做de_dust2的地图上,只有最后活着的人才能吃到鸡腿。即使hjw用步枪打yqw的手 枪,hjw也是被秒杀。
观察多次战斗后,zzy得出结论,id就是一切。假如hjw的id是yqw的id的前缀,那么hjw会被秒杀,否则可以苟活一 局。比如当hjw的id为hjw,而yqw的id为hjwaknoip2018时,hjw被秒杀。 yqw的id为 个字符串,第 局会使用第 个字符串为id。hjw的id为 个字符串,zzy想知道,对于hjw的第 个id, hjw最多可以连续苟活多少局。
Input
输入文件为
第一行两个整数 和 ,表示yqw的id总数和hjw的id总数。 接下来n 行,每行一个字符串,第i 个字符串表示yqw的第 i个id。
接下来 m行,每行一个字符串,第i 个字符串表示hjw的第i 个id。
Output
输出文件为
共 行,第 行的表示hjw第 个id的答案。
Sample Input
3 2
abcabc
aabc
abbc
aa
ba
Sample Output
1 3 对于第一个id,第二局会被秒杀,所以最多连续苟活一局。
对于第二个id,三局都不会被秒杀,所以最多连续苟活三局。

分析:先对yqw的字符串建一棵字典树。插入字符串时,在经过的每一个节点都记录一下当前字符串的 编号,然后统计当前编号与上一个编号的差,取max统计答案。对于每一个hjw的字符串,直接在字典上找到这个 位置,就可以得到答案了。

代码

#include 
#include 
#include 
#include 
#define N 5005
using namespace std;

struct trie
{
	int nxt[5],num,mx;
}tr[N * 1000];
int n,m,cnt;
char c[N],c1[N];

void ins(int len, int ss)
{
	int u = 0;
	for (int i = 1; i <= len; i++)
	{
		int v = c[i] - 'a'; 
		if (!tr[u].nxt[v]) tr[u].nxt[v] = ++cnt;
		u = tr[u].nxt[v];
		tr[u].mx = max(tr[u].mx, ss - tr[u].num - 1);
		tr[u].num = ss;
	}
}

int find(int len)
{
	int u = 0;
	for (int i = 1; i <= len; i++)
	{
		int v = c1[i] - 'a';
		if (!tr[u].nxt[v]) return n;
		u = tr[u].nxt[v];
	}
	return tr[u].mx;
}

int main()
{
//	freopen("dying1.in","r",stdin);
//	freopen("dying.out","w",stdout);
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
	{
		scanf("%s", c + 1);
		ins(strlen(c + 1), i);
	}
	for (int i = 1; i <= cnt; i++) 
		if (n - tr[i].num > tr[i].mx) tr[i].mx = n - tr[i].num; 
	while (m--)
	{
		scanf("%s", c1 + 1);
		printf("%d\n", find(strlen(c1 + 1)));
	}
	fclose(stdin);
	fclose(stdout);
}

你可能感兴趣的:(trie)