HDU 2222 Keywords Search(AC自动机模版题)

时间:2021-12-12 20:03:52

Keywords Search

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 57353    Accepted Submission(s): 18820

Problem Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.
Wiskey also wants to bring this feature to his image retrieval system.
Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.
 

 

Input First line will contain one integer means how many cases will follow by.
Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50.
The last line is the description, and the length will be not longer than 1000000.
 

 

Output Print how many keywords are contained in the description.  

 

Sample Input 15shehesayshrheryasherhs  

 

Sample Output 3  

 

题目链接:HDU 2222

AC自动机的模版题,有KMP的fail思想,即这条路上找不到了就跟着fail走向另外一条路,将之前的当作前缀继续进行匹配后一部分,若成功则加上这个节点的cnt,推荐一篇博客写得挺好:

AC自动机算法 虽然感觉不是很好理解但是只能硬着头皮看……

代码:

#include <stdio.h>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 10010;
const int M = 1000010;
struct Trie
{
int nxt[26];
int fail, cnt;
void reset()
{
fill(nxt, nxt + 26, 0);
fail = cnt = 0;
}
};
Trie L[N * 55];
int sz;
char t[55], S[M];

void init()
{
sz = 1;
L[0].reset();
}
void ins(char s[])
{
int len = strlen(s);
int u = 0;
for (int i = 0; i < len; ++i)
{
int v = s[i] - 'a';
if (!L[u].nxt[v])
{
L[sz].reset();
L[u].nxt[v] = sz++;
}
u = L[u].nxt[v];
}
++L[u].cnt;
}
namespace Aho
{
void build()
{
queue<int>Q;
L[0].fail = -1;
Q.push(0);
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for (int i = 0; i < 26; ++i)
{
int v = L[u].nxt[i];
if (!v)
continue;
Q.push(v);
if (!u)
L[v].fail = 0;
else
{
int f = L[u].fail;
while (f != -1)
{
if (L[f].nxt[i])
{
L[v].fail = L[f].nxt[i];
break;
}
f = L[f].fail;
}
if (f == -1)
L[v].fail = 0;
}
}
}
}
int Count(int u)
{
int ans = 0;
while (u)
{
if (L[u].cnt)
{
ans += L[u].cnt;
L[u].cnt = 0;
}
u = L[u].fail;
}
return ans;
}
int calc(char s[])
{
int ans = 0;
int u = 0;
int len = strlen(s);
for (int i = 0; i < len; ++i)
{
int v = s[i] - 'a';
if (L[u].nxt[v])
u = L[u].nxt[v];
else
{
int f = L[u].fail;
while (f != -1 && L[f].nxt[v] == 0)
f = L[f].fail;
if (f == -1)
u = 0;
else
u = L[f].nxt[v];
}
if(L[u].cnt)
ans += Count(u);
}
return ans;
}
}
int main(void)
{
int T, n;
scanf("%d", &T);
while (T--)
{
init();
scanf("%d", &n);
while (n--)
{
scanf("%s", t);
ins(t);
}
Aho::build();
scanf("%s", S);
printf("%d\n", Aho::calc(S));
}
return 0;
}