简单来说就是Trie+KMP,关键是对fail的理解,用了一天时间学并码了出来……同时感谢ZW大神的板子~~~(http://paste.ubuntu.com/22260465/)
#include <cstdio>
#include <cstring>
#define maxn 1000000+5
int T,n,val[maxn],ch[maxn][26],sz,fail[maxn],h,t,q[maxn];
char s[55],st[maxn];
void insert(char *s)//相当于Trie
{
int u=0,n=strlen(s);
for (int i=0;i<n;i++)
{
int c=s[i]-'a';
if (!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]++;
}
void get_fail()//BFS求fail数组 ,相当于KMP
{
h=t=0;//初始化队列
for (int i=0;i<26;i++)
if (ch[0][i]) q[++t]=ch[0][i];
while (h<t)
{
int u=q[++h];
for (int i=0;i<26;i++)
if (ch[u][i]){
int k;
for (k=fail[u];k&&!ch[k][i];k=fail[k]);
fail[q[++t]=ch[u][i]]=ch[k][i];
}
}
}
int query(char *s)
{
int ans=0,n=strlen(s),u=0;
for (int i=0;i<n;i++)
{
int c=s[i]-'a',k;
while (!ch[u][c]&&u) u=fail[u];
int tmp=u=ch[u][c];
while (tmp)
{
if (val[tmp]) ans+=val[tmp],val[tmp]=0;
else break;
tmp=fail[tmp];
}
}
return ans;
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
sz=1;val[0]=0;
memset(ch[0],0,sizeof(ch[0]));//一开始把sizeof(ch[0])写成sizeof(0)调了很久才发现~~~
memset(fail,0,sizeof(fail));
for (int i=0;i<n;i++)
scanf("%s",s),insert(s);
get_fail();
scanf("%s",st);
printf("%d\n",query(st));
}
return 0;
}
附上一份Trie和KMP~~~
//POJ3630 Trie模板题
#include <cstdio>
#include <cstring>
#define maxn 100000+5
int ch[maxn][20],T,n,val[maxn],sz;
bool ok;
char s[20];
int insert(char *s)
{
int n=strlen(s),u=0,f1=1,f2=1;
for (int i=0;i<n;i++)
{
int c=s[i]-'0';
if (!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
f1=0;
}
u=ch[u][c];
if (val[u]) f2=0;
}
val[u]=1;
if (f1||!f2) return true;
return false;
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
memset(ch[0],0,sizeof(ch));
sz=1;val[0]=0;
ok=0;
for (int i=0;i<n;i++){
scanf("%s",s);
if (insert(s))ok=1;
}
if (ok)printf("NO\n");
else printf("YES\n");
}
}
//KMP3375
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
int k,i,j,xx=-1,next[1000000];
string s1,s2;
int plen,slen,len;
void get_next(string str,int* next){
next[0]=-1, len=str.length();
for (int i=1;i<len;i++)
{
k=next[i-1];
while (k>-1&&str[i]!=str[k+1]) k=next[k];
if (str[k+1]==str[i]) next[i]=k+1;
else next[i]=-1;
}
}
int KMP(string str,string ptr,int* next){
k=-1;
slen=str.length(),plen=ptr.length();
for ( i=0;i<slen;i++)
{
while (k>-1&&str[i]!=ptr[k+1])
k=next[k];
if (str[i]==ptr[k+1])k++;
if (k==plen-1) k=next[k],
printf("%d\n",i+2-plen);
}
//return p_now==plen ? (s_now-plen) :-1;
}
int main(){
cin>>s2>>s1;
get_next(s1,next);
//printf("%d",KMP(s2,s1,next));
KMP(s2,s1,next);
for (int i=0;i<plen;i++) printf("%d ",next[i]+1);
return 0;
}