http://acm.hdu.edu.cn/showproblem.php?pid=3065
3 AA BB CC ooxxCC%dAAAoen....END
AA: 2 CC: 1HintHit: 题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。 计数策略也可一定程度上从Sample中推测。
/** hdu3065 AC自动机-每个标准串在模式串中出现的次数 题目大意:给定一些字符串,求一下早给定的模式串中每一个出现了多少次,统计一下并输出 解题思路:AC自动机模板题,建立自动机的时候统计一下每个字符串的编号 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> using namespace std; char str[1010][1010]; struct Trie { int next[1010*50][128],fail[1010*50],end[1010*50]; int root,L; int newnode() { for(int i=0; i<128; i++) { next[L][i]=-1; } end[L++]=-1; return L-1; } void init() { L=0; root=newnode(); } void insert(char *s,int id) { int len=strlen(s); int now=root; for(int i=0; i<len; i++) { if(next[now][s[i]]==-1) next[now][s[i]]=newnode(); now=next[now][s[i]]; } end[now]=id; } void build() { queue<int>Q; fail[root]=root; for(int i=0; i<128; 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<128; 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 num[1010]; void query(char *buf,int n) { memset(num,0,sizeof(num)); int len=strlen(buf); int now=root; for(int i=0; i<len; i++) { now=next[now][buf[i]]; int temp=now; while(temp!=root) { if(end[temp]!=-1) num[end[temp]]++; temp=fail[temp]; } } for(int i=0; i<n; i++) { if(num[i]>0) printf("%s: %d\n",str[i],num[i]); } } 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 < 128; j++) printf("%2d ",next[i][j]); printf("]\n"); } } } ac; char buf[2000010]; int main() { int n; while(~scanf("%d",&n)) { ac.init(); for(int i=0; i<n; i++) { scanf("%s",str[i]); ac.insert(str[i],i); } ac.build(); scanf("%s",buf); ac.query(buf,n); //ac.debug(); } return 0; }
3 AA BB CC ooxxCC%dAAAoen....END
AA: 2 CC: 1HintHit: 题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。 计数策略也可一定程度上从Sample中推测。