http://acm.hdu.edu.cn/showproblem.php?pid=2222
1 5 she he say shr her yasherhs
3
AC自动机代码简单又容易理解,终于明白为什么写Trie图的那么少了
#include <cstdio> #include <queue> using namespace std; const int MAXNODE=10000*50+5; int T,n; char s[1000005]; struct Trie { int nxt[MAXNODE][26],fail[MAXNODE],ed[MAXNODE];//数组模拟 int l; const static int root=0; Trie() { clear(); } int newNode() {//取一个结点 for(int i=0;i<26;++i) nxt[l][i]=-1; ed[l]=0;//ed[l]表示从根到当前结点的模式串出现的次数 return l++; } void insert(char *p) {//插入一个模式串 int cur=root; while(*p) { if(nxt[cur][*p-'a']==-1) nxt[cur][*p-'a']=newNode(); cur=nxt[cur][*p-'a']; ++p; } ++ed[cur]; } void build() {//建立fail指针 int cur,i; queue<int> q; fail[root]=root; for(i=0;i<26;++i) if(nxt[root][i]==-1)//如果根结点无i子结点 nxt[root][i]=root; else { fail[nxt[root][i]]=root; q.push(nxt[root][i]); } while(!q.empty()) { cur=q.front(); q.pop(); for(i=0;i<26;++i) if(nxt[cur][i]==-1)//如果当前结点无i子结点 nxt[cur][i]=nxt[fail[cur]][i];//当前结点的i子结点指针 指向 当前结点fail指针指向的结点的i子结点 else { fail[nxt[cur][i]]=nxt[fail[cur]][i];//当前结点i子结点的fail指针 指向 当前结点fail指针指向的结点的i子结点 q.push(nxt[cur][i]); } } } int query(char *p) { int cur=root,ans=0,tmp; while(*p) { cur=nxt[cur][*p-'a']; tmp=cur; while(tmp!=root) {//遍历与当前形成的串有公共后缀的串 ans+=ed[tmp]; ed[tmp]=0;//由于只需要统计出现了关键词,所需需要置0,防止重复计算 tmp=fail[tmp]; } ++p; } return ans; } void clear() { l=root; newNode(); } }ac; int main() { scanf("%d",&T); while(T--) { ac.clear(); scanf("%d",&n); while(n--) { scanf("%s",s); ac.insert(s); } ac.build(); scanf("%s",s); printf("%d\n",ac.query(s)); } return 0; }