http://acm.hust.edu.cn/vjudge/problem/16403
题意:给定n个单词,一个字符串,问字符串中出现了多少个单词。(若单词her,he,字符串aher中出现了两个单词)
题解:
每个单词末尾节点sum=1;
find的时候每个点都顺着fail往上跳,加上该节点的sum,然后将这个sum清了;
注意同一个单词出现多次只算一次。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<queue>
6 using namespace std;
7
8 const int N=10100,L=1000100;
9 char s[L];
10 int num,n;
11 struct node{
12 int son[30];
13 int fail,cnt;
14 }a[N*60];
15 queue<int> q;
16
17 void clear(int x)
18 {
19 a[x].cnt=0;
20 a[x].fail=0;
21 memset(a[x].son,0,sizeof(a[x].son));
22 }
23
24 void trie(char *c)
25 {
26 int l=strlen(c);
27 int x=0;
28 for(int i=0;i<l;i++)
29 {
30 int t=c[i]-'a'+1;
31 if(!a[x].son[t])
32 {
33 num++;
34 clear(num);
35 a[x].son[t]=num;
36 }
37 x=a[x].son[t];
38 }
39 a[x].cnt++;
40 }
41
42 void buildAC()
43 {
44 while(!q.empty()) q.pop();
45 for(int i=1;i<=26;i++)
46 if(a[0].son[i]) q.push(a[0].son[i]);
47 while(!q.empty())
48 {
49 int x=q.front();q.pop();
50 int fail=a[x].fail;
51 for(int i=1;i<=26;i++)
52 {
53 int y=a[x].son[i];
54 if(y)
55 {
56 a[y].fail=a[fail].son[i];
57 q.push(y);
58 }
59 else a[x].son[i]=a[fail].son[i];
60 }
61 }
62 }
63
64 int find(char *c)
65 {
66 int l=strlen(c);
67 int x=0,ans=0;
68 for(int i=0;i<l;i++)
69 {
70 int t=c[i]-'a'+1;
71 while(x && !a[x].son[t]) x=a[x].fail;
72 x=a[x].son[t];
73 int p=x;
74 while(p && a[p].cnt!=-1)
75 {
76 ans+=a[p].cnt;
77 a[p].cnt=-1;
78 p=a[p].fail;
79 }
80 }
81 return ans;
82 }
83
84 int main()
85 {
86 freopen("a.in","r",stdin);
87 freopen("a.out","w",stdout);
88 int T;
89 scanf("%d",&T);
90 while(T--)
91 {
92 scanf("%d",&n);
93 num=0;
94 clear(0);
95 for(int i=1;i<=n;i++)
96 {
97 scanf("%s",s);
98 trie(s);
99 }
100 buildAC();
101 scanf("%s",s);
102 printf("%d
",find(s));
103 }
104 return 0;
105 }