AC自動機跟隨Kuangbing學習筆記
阿新 • • 發佈:2019-01-30
//====================== // HDU 2222 // 求目標串中出現了幾個模式串 //輸入 //1 //5 //she //he //say //shr //her //yasherhs //==================== #include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> #include<queue> using namespace std; struct Trie { int next[500010][26],fail[500010],end[500010]; 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() { 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; //第一層的失敗指標指向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 s[300]; char buff[1000005]; Trie ac; void input() { int n; cin>>n; ac.init(); for(int i=1;i<=n;i++) { scanf("%s",s); ac.insert(s); } ac.build(); } int main() { int T; cin>>T; while(T--) { input(); scanf("%s",buff); printf("%d\n",ac.query(buff)); } }