[Trie] Jzoj P5795 词典

Description

 

Input

第一行两个数n,m,表示有n个字符串,m个询问。
接下来n行,每行一个字符串Ti 。
再接下来m行,每行一个字符串Si 。

Output

对于每个询问,输出一个ansi表示答案。
 

Sample Input

3 2
abcabc
aabc
abbc
aa
ba  

Sample Output

1
3 
 

Data Constraint

题解

  • 发现Σlen[t[i]]<=5*10^6,显然可以建trie
  • 考虑如何找最长全0串
  • 分三种情况:
  • ①没有走过的点,当前i前面的都没有包含它的,为i-1
  • ②走过的点,再上次走到当前层的是第i个字符串,然后走到这个时为i-1-w[p]
  • ③最后的w[p]到n

代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 int n,m,tot=1,trie[5000001][3],w[5000001],k[5000001];
 6 char str[5000001];
 7 void insert(int x)
 8 {
 9     int len=strlen(str+1),p=1;
10     for (int i=1;i<=len;i++)
11     {
12         int ch=str[i]-'a';
13         if (!trie[p][ch]) p=trie[p][ch]=++tot,k[p]=x-1;
14         else p=trie[p][ch],k[p]=max(k[p],x-1-w[p]);
15         w[p]=x;
16     }
17 }
18 int search()
19 {
20     int len=strlen(str+1),p=1;
21     for (int i=1;i<=len;i++)
22     {
23         int ch=str[i]-'a';
24         if (trie[p][ch]==0) return n;
25         p=trie[p][ch];
26     }
27     return max(k[p],n-w[p]);
28 }
29 int main()
30 {
31     freopen("word.in","r",stdin);
32     freopen("word.out","w",stdout);
33     scanf("%d%d",&n,&m);
34     for (int i=1;i<=n;i++) scanf("%s",str+1),insert(i);
35     for (int i=1;i<=m;i++) scanf("%s",str+1),printf("%d\n",search());
36     return 0;
37 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9457057.html