HDOJ 2222 Keywords Search (AC自动机)
题意:给n个单词和一个文本,求有多少个单词出现在文本中。
据说这题是AC自动机的模版题。这题也是我写的第一个AC自动机的题。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define LEN 55 #define N 10010 int n,node; int next[N*LEN][26]; int cnt[N*LEN]; int fail[N*LEN]; void init() { memset(next[0],0,sizeof(next[0])); node=1; } void add(int cur,int k) { memset(next[node],0,sizeof(next[node])); cnt[node]=0; next[cur][k]=node++; } void insert(char s[]) { int i,k,cur; for(i=cur=0;s[i];i++) { k=s[i]-'a'; if(!next[cur][k]) add(cur,k); cur=next[cur][k]; } cnt[cur]++; } void build() { int cur,nxt,k,tmp; queue<int> q; fail[0]=0; q.push(0); while(!q.empty()) { cur=q.front(),q.pop(); for(k=0;k<26;k++) { nxt=next[cur][k]; if(!nxt) continue; if(cur==0) fail[nxt]=0; else { for(tmp=fail[cur];!next[tmp][k] && tmp;tmp=fail[tmp]); fail[nxt]=next[tmp][k]; } q.push(nxt); } } } int match(char s[]) { int i,k,cur,ans=0; for(cur=i=0;s[i];i++) { k=s[i]-'a'; for(;next[cur][k]==0 && cur;cur=fail[cur]); if(next[cur][k]) cur=next[cur][k]; int tmp=cur; while(tmp) { ans+=cnt[tmp]; cnt[tmp]=0; tmp=fail[tmp]; } } return ans; } int main() { int k; char tmp[LEN]; char t[1000001]; scanf("%d",&k); while(k--) { scanf("%d",&n); init(); for(int i=0;i<n;i++) { scanf("%s",tmp); insert(tmp); } build(); scanf("%s",t); printf("%d\n",match(t)); } return 0; }