hdu 2222 AC自动机模板题
2013-08-20 11:46
459 查看
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define maxn 241000 #define sigma_size 26 char s[60], t[maxn*5]; struct ac { int ch[maxn][sigma_size]; int val[maxn], f[maxn], last[maxn]; int next; void init() { next = 0; memset(ch[0], 0, sizeof(ch[0])); memset(val, 0, sizeof(val)); } void insert(char *s, int v) { int len = strlen(s), cur = 0; for (int i=0; i<len; i++) { int idx = s[i] - 'a'; if (!ch[cur][idx]) { ch[cur][idx] = ++next; memset(ch[next], 0, sizeof(ch[next])); } cur = ch[cur][idx]; } val[cur] += v; } void getFail() { queue<int>q; f[0] = 0; //初始化队列 for (int i=0; i<sigma_size; i++) if ( ch[0][i] ) { f[ ch[0][i] ] = 0;//第一个字母匹配失败只能指向0 last[ ch[0][i] ] = 0;//last后缀也只能指向0 q.push(ch[0][i]); } while (!q.empty()) { int cur = q.front(); q.pop(); for (int i=0; i<sigma_size; i++) { int u = ch[cur][i]; // if (!u)//u结点下i位置没有字母 // continue;//继续下一个位置 if (!u) { ch[cur][i] = ch[ f[cur] ][i]; continue; } q.push(u); int j = f[cur];//失败指针 while (j && !ch[j][i])//沿着失败指针走,ch[j][i]=0时没有此结点故继续 j = f[j]; f[u] = ch[j][i];//计算出结点u的失败指针 last[u] = val[ f[u] ] ? f[u] : last[ f[u] ];//f[u]处是否是单词结点 } } } void getfail() { queue<int>q; q.push(0);//根结点入队 while (!q.empty()) { int cur = q.front();//取对头 q.pop(); for (int i=0; i<sigma_size; i++) { int u = ch[cur][i]; if (u)//u是否存在 { if (cur==0)//如果父亲结点是根结点,失败指针和后缀链接指向0 f[u] = last[u] = 0; else { int j = f[cur];//父亲的失败指针 while (j && !ch[j][i])//沿着父亲的失败指针走 j = f[j]; f[u] = ch[j][i];//找到u的失败指针 last[u] = val[ f[u] ] ? f[u] : last[ f[u] ];//f[u]处是否是单词结点 } q.push( ch[cur][i] ); } else ch[cur][i] = ch[ f[cur] ][i];//不存在这一点,指向父亲结点的失败指针的第i个儿子 } } } int find(char *t) { int len = strlen(t), j = 0, ans = 0, temp; for (int i=0; i<len; i++) { int idx= t[i] - 'a'; // while (j && !ch[j][idx])//沿着失败指着走 // j = f[j]; j = ch[j][idx];//找到重新匹配的结点 temp = j; while (temp && val[temp])//该结点是单词 { ans += val[temp];//计数 val[temp] = 0;//标记已算过 temp = last[temp];//查找后缀串 } } return ans; } }ac; int main() { int n, ncase; scanf("%d", &ncase); while (ncase--) { scanf("%d", &n); ac.init(); for (int i=0; i<n; i++) { scanf("%s", s); ac.insert(s, 1); } ac.getFail(); scanf("%s", t); printf("%d\n", ac.find(t)); } return 0; }
相关文章推荐
- HDU 2222 Keywords Search 【AC自动机(模板题)】
- HDU 2222 Keywords Search(AC自动机 模板)
- 【模板练习——AC自动机】Keywords Search HDU - 2222
- HDU 2222 Keywords Search 【AC自动机模板】
- hdu 2222 AC自动机模板题
- [AC自动机模板题] HDU 2222 Keywords Search
- HDU 2222 Keywords Search(我的第一道AC自动机,模板题)
- HDU2222 AC自动机模板
- AC自动机学习小记 Hdu 2222 Keywords Search (模板)
- hdu 2222 Keywords Search(AC自动机模板)
- 文章标题 HDU 2222 : Keywords Search (AC自动机模板)
- AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222
- hdu 2222 Keywords Search(AC自动机模板)
- HDU 2222 ac自动机入门模板题
- AC自动机入门+模板 (HDU 2222)
- AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222
- HDU 2222 Keywords Search(AC自动机模板)
- CUGB专题训练之数据结构:E - Keywords Search(HDU 2222 AC自动机经典入门模板题)
- HDU2222 AC自动机模板
- 【HDU-2222】Keywords Search(AC自动机模板)