HDU 2222 AC自动机入门题

来源:互联网 发布:java循环语句 编辑:程序博客网 时间:2024/06/01 16:14
#include<cstdio>#include<iostream>#include<queue>#include<cstring>#include<algorithm>using namespace std;#define MAX_N 500010struct Trie{//  子节点指针        指向和当前节点的某个后缀匹配的最长前缀的位置  末尾节点int next[MAX_N][26], fail[MAX_N], end[MAX_N];int root, L;int newnode()//建立新节点{for (int i = 0; i < 26; i++)next[L][i] = -1;end[L++]=0;return L - 1;}void init(){L = 0;root = newnode();}void insert(char buf[])//插入模式串{int len = strlen(buf);int now = root;for (int i = 0; i < len; i++){if (next[now][buf[i] - 'a'] == -1)//没有这个节点{next[now][buf[i] - 'a'] = newnode();}now = next[now][buf[i] - 'a'];}end[now]++;//标记末尾节点}void build()//BFS构造fail指针{//如果失配指针指向root,则说明当前序列的任意后缀不会是某个单词的前缀queue<int>Q;fail[root] = root;for (int i = 0; i < 26; i++){if (next[root][i] == -1)next[root][i] = root;else {fail[next[root][i]] = root;Q.push(next[root][i]);}}while (!Q.empty()){int now = Q.front();Q.pop();for (int i = 0; i < 26; i++)if (next[now][i] == -1)next[now][i] = next[fail[now]][i];else{fail[next[now][i]] = next[fail[now]][i];Q.push(next[now][i]);}}}int query(char buf[]){int len = strlen(buf);int now = root;int res = 0;for (int i = 0; i < len; i++){now = next[now][buf[i] - 'a'];int temp = now;while (temp!=root){res += end[temp];end[temp] = 0;temp = fail[temp];}}return res;}void debug(){for (int i = 0; i < L; i++){printf("id = %3d,fail = %3d,end =%3d,chi=[", i, fail[i], end[i]);for (int j = 0; j < 26; j++)printf("%2d", next[i][j]);printf("]\n");}}};char buf[1000010];Trie ac;int main(){int T;int n;scanf("%d", &T);while (T--){scanf("%d", &n);ac.init();for (int i = 0; i < n; i++){scanf("%s", buf);ac.insert(buf);}ac.build();scanf("%s", buf);printf("%d\n", ac.query(buf));}return 0;}

原创粉丝点击