AC自动机-模板
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 5 using namespace std; 6 7 const int _N = 1000000; 8 9 int rt = 1, TrieCnt = 1; 10 queue<int> Q; 11 12 struct node { 13 int w, fail, son[3]; 14 } T[_N]; 15 16 char str[300]; 17 int f[1200][3200], N, K; 18 19 void Extend() 20 { 21 int p = rt, len = strlen(str+1); 22 for (int i = 1; i <= len; ++i) { 23 int &son = T[p].son[str[i]-'A']; 24 if (!son) son = ++TrieCnt; 25 p = son; 26 } 27 ++T[p].w; 28 } 29 30 void Init() 31 { 32 while (!Q.empty()) Q.pop(); 33 Q.push(rt), T[rt].fail = rt; 34 while (!Q.empty()) { 35 int p = Q.front(); Q.pop(); 36 T[p].w += T[T[p].fail].w; 37 for (int i = 0; i < 3; ++i) { 38 int &son = T[p].son[i], j; 39 for (j = T[p].fail; j != rt && !T[j].son[i]; j = T[j].fail); 40 int tmp = T[j].son[i]; 41 if (tmp && tmp != son) j = tmp;//把 j 改为 son 的父亲的 fail 链上最近的点的儿子(由定义不能为 son 自己) 42 if (son) T[son].fail = j, Q.push(son); 43 else son = j;//强行给自己找一个儿子! 注意这里非常重要!注意这里非常重要!注意这里非常重要! 44 } 45 } 46 return; 47 } 48 49 int DP() 50 { 51 int i, j; 52 for (i = 1; i <= TrieCnt; ++i) f[0][i] = -1; 53 f[0][rt] = 0; 54 for (i = 1; i <= K; ++i) { 55 for (j = 1; j <= TrieCnt; ++j) 56 f[i][j] = -1; 57 for (j = 1; j <= TrieCnt; ++j) { 58 if (f[i-1][j] == -1) continue; 59 int p = j; 60 for (int g = 0; g < 3; ++g) { 61 int son = T[p].son[g]; 62 if (son) f[i][son] = max(f[i][son], f[i-1][j]+T[son].w); 63 } 64 } 65 } 66 int ans = 0; 67 for (i = 1; i <= TrieCnt; ++i) ans = max(ans, f[K][i]); 68 return ans; 69 } 70 71 int main() 72 { 73 scanf("%d%d", &N, &K); 74 while (N--) scanf("%s", str+1), Extend(); 75 Init(); 76 printf("%d\n", DP()); 77 return 0; 78 }
NKOJ1960
P1960【自动机】关键词搜索 | |
|
问题描述
如今,搜索引擎像Google,Baidu等搜索引擎已经成为了人们生活的一部分。
韦斯利也想把这个搜索功能加入到他的图片检索系统中。
每张图片都有一个很长的相关描述,当用户们输入了一些关键词去查找图片,韦斯利的系统将会找出与用户输入的关键词匹配数最多的图片并把他显示给用户。
简单的说,给出一段描述图片的文字,再给你一些关键词,你要回答这段文字中匹配了多少个关键词。
输入格式
第一行一个整数n,表示有n个关键词(n<=10000)
接下来n行,每行表示一个关键词,每个关键词由小写字母构成,且长度不超过50
最后一行,表示描述图片的文字,由小写字母构成且长度不超过1000000
输出格式
一个整数,表示最多匹配的关键词数
样例输入
5
she
he
say
shr
her
yasherhs
样例输出
3