zoj 3228 Searching the String
给你一个主串
再给你很多模式串
对于每个串分别判断它在主串中出现了几次
每个模式串还有一个flag标记 0:匹配的时候可以重叠 1:匹配的时候不能重叠
在匹配的时候判断当期节点上一次匹配的时候在主串中的位置与当前位置之差是否大于模式串的长度即可
View Code
#include<cstdio> #include<cstring> const int MM = 500005,NC = 26; int N; char str[100010]; char s[100010]; int x[100010]; int flag[100010]; struct trie{ int ch[NC],fail,f[2],pos,len; void init(){ memset(ch,0,sizeof(ch)); fail=f[0]=f[1]=len=0; pos=-1; } }a[MM]; int cnt,rt,q[MM],front,last; void Init(){ cnt=1; rt=cnt++; a[0].init(); for(int i=0;i<NC;i++) a[0].ch[i]=rt; a[1].init(); memset(x,0,sizeof(x)); } void Ins(char *in,int flag,int num){ int now=rt,i=0; for(;*in;++in){ i++; int id=*in-'a'; if(!a[now].ch[id]){ a[cnt].init(); a[now].ch[id]=cnt++; } now=a[now].ch[id]; } a[now].len=i; a[now].f[flag]=1; x[num]=now; } void build(){ front=last=0; q[front++]=rt; while(last<front){ int t=q[last++]; for(int i=0;i<NC;i++){ int tt=a[t].ch[i]; int ff=a[t].fail; if(a[t].ch[i]){ a[tt].fail=a[ff].ch[i]; q[front++]=tt; } else a[t].ch[i]=a[ff].ch[i]; } } } void AC(char *str){ int i=0,cur=rt; for(;str[i];i++){ int id=str[i]-'a'; cur=a[cur].ch[id]; int p=cur; while(p!=rt) { if(a[p].f[0]) a[p].f[0]++; if(a[p].f[1]) { if(i-a[p].pos >= a[p].len) { a[p].pos=i; a[p].f[1]++; } } p=a[p].fail; } } } int main(){ int t,n,ca=0,i; while(scanf("%s",s)!=EOF){ Init(); scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d%s",&flag[i],str); Ins(str,flag[i],i); } build(); AC(s);printf("Case %d\n",++ca); for(i=1;i<=n;i++) { printf("%d\n",a[x[i]].f[flag[i]]-1); } puts(""); } return 0; }