题目大意:给出一些字符串 ,再给出一段文字,问文字中出现多少个单词
解决:AC自动机
#include <iostream> #include <cstring> #include <queue> #include <cstdio> using namespace std; #define s scanf int top; struct node { int cnt; int fail; int next[26]; }; node tree[400000]; char mai[1000005]; void init() { top=1; memset(tree[0].next,0,sizeof(tree[0].next)); //刚开始的时候初始化,是在node的构造函数中实现的,但是由于是多组测试数据,所以 //错误了好几次这次,就应该在初始化,和需要新的结点的时候在初始化 tree[top].cnt=0; } void insert_trie(char str[]) { int id,i=0; while(*str) { id=*str-'a'; if(!tree[i].next[id]) { tree[i].next[id]=top; memset(tree[top].next,0,sizeof(tree[top].next)); tree[top].cnt=0; top++; } i=tree[i].next[id]; str++; } tree[i].cnt++; } void build_fail() { tree[0].fail=-1; queue<int> q; q.push(0); while(!q.empty()) { int now=q.front(); q.pop(); for(int i=0;i<26;i++) { int tmp=tree[now].next[i]; if(tmp) { int p; for(p=tree[now].fail;p!=-1;p=tree[p].fail) if(tree[p].next[i]) { tree[tmp].fail=tree[p].next[i]; break; } if(p==-1){tree[tmp].fail=0;} q.push(tmp); } } } } void query(char str[]) { int id,sum=0,p=0; while(*str) { id=*str-'a'; //不匹配的情况,找到根节点,或者是找到匹配的地方 while(tree[p].next[id]==0 && p)p=tree[p].fail; if(tree[p].next[id]==0)p=0; else p=tree[p].next[id]; //匹配或者是根节点的情况,沿着fail一直找到跟,将所有的一该字母结束的串的情况 都 算上。 int tmp=p; while(tmp && tree[tmp].cnt) { sum+=tree[tmp].cnt; tree[tmp].cnt=0; tmp=tree[tmp].fail; } str++; } printf("%d\n",sum); } int main() { int icase; s("%d",&icase); while(icase--) { init(); int n; char str[60]; s("%d",&n); while(n--) { s("%s",str); insert_trie(str); } build_fail(); s("%s",mai); query(mai); } // system("pause"); return 0; }