Keywords Search

OJ题号:HDU2222

思路:

AC自动机。

同一个模板串只能算一遍,所以每找到一个模板串就要吧当前串的cnt变成0,避免重复计算。注意可能会有相同的模板串,所以要用cnt来保存出现的次数。

第一次做AC自动机,主要参考刘汝佳的训练指南和网上一个题解
http://blog.csdn.net/morgan_xww/article/details/7834338 
 1 #define maxnode 500000
 2 #define sigma_size 26
 3 #include<queue>
 4 #include<cstdio>
 5 #include<cstring>
 6 using namespace std;
 7 struct AC {
 8     int ch[maxnode][sigma_size];
 9     int val[maxnode],last[maxnode],f[maxnode],cnt[maxnode];
10     int sz;
11     int idx(char c) {
12         return c-'a';
13     }
14     void reset() {
15         memset(ch[0],0,sizeof(ch[0]));
16         sz=1;
17     }
18     void insert(char *s) {
19         int u=0,n=strlen(s);
20         for(int i=0;i<n;i++) {
21             int c=idx(s[i]);
22             if(!ch[u][c]) {
23                 memset(ch[sz],0,sizeof(ch[sz]));
24                 cnt[sz]=val[sz]=0;
25                 ch[u][c]=sz++;
26             }
27             u=ch[u][c];
28         }
29         val[u]=1;
30         cnt[u]++;
31     }
32     void getFail() {
33         queue<int> q;
34         f[0]=0;
35         //Initialize
36         for(int c=0;c<sigma_size;c++) {
37             int u=ch[0][c];
38             if(u) {
39                 f[u]=0;
40                 q.push(u);
41                 last[u]=0;
42             }
43         }
44         //calc last in BFS way
45         while(!q.empty()) {
46             int r=q.front();
47             q.pop();
48             for(int c=0;c<sigma_size;c++) {
49                 int u=ch[r][c];
50                 if(!u) {
51                     ch[r][c]=ch[f[r]][c];
52                     continue;
53                 }
54                 q.push(u);
55                 int v=f[r];
56                 while(v&&!ch[v][c]) v=f[v];
57                 f[u]=ch[v][c];
58                 last[u]=val[f[u]]?f[u]:last[f[u]];
59             }
60         }
61     }
62     int find(char *t) {
63         int n=strlen(t),j=0,ans=0;
64         for(int i=0;i<n;i++) {
65             int c=idx(t[i]);
66             j=ch[j][c];
67             int u=j;
68             while(u) {
69                 ans+=cnt[u];
70                 cnt[u]=0;
71                 u=f[u];
72             }
73         }
74         return ans;
75     }
76 };
77 AC ac;
78 int main() {
79     int t;
80     scanf("%d",&t);
81     while(t--) {
82         int n;
83         scanf("%d",&n);
84         ac.reset();
85         while(n--) {
86             char s[1000001];
87             scanf("%s",s);
88             ac.insert(s);
89         }
90         ac.getFail();
91         char s[51];
92         scanf("%s",s);
93         printf("%d\n",ac.find(s));
94     }
95     return 0;
96 }

注:本随笔整理自QQ空间旧文。发布时间为2017年3月15日。

查看原文

posted @ 2017-05-06 15:37  skylee03  阅读(160)  评论(0编辑  收藏  举报