hdu 2222 keywords search

https://vjudge.net/problem/HDU-2222

题意:

给出若干个模式串,然后给出文本串,问这些模式串在文本串中出现了几次。

思路:

妥妥的ac自动机,没有什么好说的,直接上模板,不过要注意maxn的大小是跟文本串的长度一样的。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <queue>
  4 using namespace std;
  5 
  6 const int maxn = 1000005;
  7 
  8 struct ac_auto
  9 {
 10     int chd[maxn][26],v[maxn],f[maxn],last[maxn],sz,ans;
 11 
 12     void init()
 13     {
 14         sz = 1;
 15         ans = 0;
 16 
 17         memset(chd[0],0,sizeof(chd[0]));
 18         memset(f,0,sizeof(f));
 19         memset(v,0,sizeof(v));
 20     }
 21 
 22     void insert(char *p)
 23     {
 24         int cur = 0;
 25         for (;*p;p++)
 26         {
 27             if (!chd[cur][*p-'a'])
 28             {
 29                 memset(chd[sz],0,sizeof(chd[sz]));
 30                 chd[cur][*p-'a'] = sz++;
 31             }
 32             cur = chd[cur][*p-'a'];
 33         }
 34         v[cur]++;
 35     }
 36 
 37     bool query(char *p)
 38     {
 39         int cur = 0;
 40 
 41         for (;*p;p++)
 42         {
 43             if (!chd[cur][*p-'a']) break;
 44             cur = chd[cur][*p-'a'];
 45         }
 46 
 47         return v[cur] && (!(*p));
 48     }
 49 
 50     void getfail()
 51     {
 52         queue<int> q;
 53 
 54         f[0] = 0;
 55 
 56         for (int c = 0;c < 26;c++)
 57         {
 58             int u = chd[0][c];
 59 
 60             if (u)
 61             {
 62                 f[u] = 0;q.push(u);
 63                 last[u] = 0;
 64             }
 65         }
 66 
 67         while (!q.empty())
 68         {
 69             int r = q.front();q.pop();
 70 
 71             for (int c = 0;c < 26;c++)
 72             {
 73                 int u = chd[r][c];
 74 
 75                 if (!u)
 76                 {
 77                     chd[r][c] = chd[f[r]][c];
 78                     continue;
 79                 }
 80 
 81                 q.push(u);
 82 
 83                 int vv = f[r];
 84 
 85                 while (vv&&!chd[vv][c]) vv = f[vv];
 86                 f[u] = chd[vv][c];
 87                 last[u] = v[f[u]] ? f[u] : last[f[u]];
 88             }
 89         }
 90     }
 91 
 92     void solve(int j)
 93     {
 94         if (!j) return;
 95         if (v[j])
 96         {
 97             ans += v[j];
 98             v[j] = 0;
 99         }
100 
101         solve(last[j]);
102     }
103 
104     void find(char *t)
105     {
106         int n = strlen(t),j = 0;
107         getfail();
108 
109         for (int i = 0;i < n;i++)
110         {
111             j = chd[j][t[i]-'a'];
112 
113             if (v[j]) solve(j);
114             else if (last[j]) solve(last[j]);
115         }
116     }
117 }ac;
118 
119 char tt[1000005];
120 
121 int main()
122 {
123     int t;
124 
125     scanf("%d",&t);
126 
127     while (t--)
128     {
129         ac.init();
130 
131         int n;
132 
133         scanf("%d",&n);
134 
135         for (int i = 0;i < n;i++)
136         {
137             char tmp[60];
138 
139             scanf("%s",tmp);
140 
141             ac.insert(tmp);
142         }
143 
144         scanf("%s",tt);
145 
146         ac.find(tt);
147 
148         printf("%d\n",ac.ans);
149     }
150 
151     return 0;
152 }

 

posted @ 2017-07-28 20:27  qrfkickit  阅读(167)  评论(0编辑  收藏  举报