http://blog.henix.info/blog/poj-2778-aho-corasick-dp.html 讲得很好
1.当要转移的次数很多,有牵涉到很多关系时,用矩阵
2.fail指针的理解
用数组的写法更容易理解,抄师兄的代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define mod 100000
#define CH 4
#define maxnode 110
#define ll long long
int ch[maxnode][CH],val[maxnode],fail[maxnode],que[maxnode*2],sz;
int sw[300];
int m,n;
void _insert(char *str)
{
int u=0,len=strlen(str);
for(int i=0;i<len;++i)
{
if(!ch[u][sw[str[i]]])
{
val[sz]=0;
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][sw[str[i]]]=sz++;
}
u=ch[u][sw[str[i]]];
}
val[u]=1;
}
void getfail()
{
int front=0,rear=0;
for(int i=0;i<CH;++i)
if(ch[0][i])
{
fail[ch[0][i]]=0;
que[rear++]=ch[0][i];
}
while(front<rear)
{
int u=que[front++];
for(int i=0;i<CH;++i)
{
if(ch[u][i])
{
que[rear++]=ch[u][i];
fail[ch[u][i]]=ch[fail[u]][i];
val[ch[u][i]] |= val[ch[fail[u]][i]];
}
else ch[u][i]=ch[fail[u]][i];
// 把不存在的边也补上,就能对所有转移都一视同仁
// 不再 while(j&&str[ch[v][i]]!=str[ch[u][i]]) v=f[v]
}
}
}
struct matrix
{
int n;
ll m[110][110];
matrix(int _n=0){n=_n;memset(m,0,sizeof(m));}
matrix operator*(matrix &r)
{
matrix t(n);
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
{
t.m[i][j]=0;
for(int k=0;k<n;++k)
{
t.m[i][j]+=m[i][k]*r.m[k][j];
if(t.m[i][j]>=mod)
t.m[i][j]%=mod;
}
}
return t;
}
};
void getmatrix(matrix &a)
{
for(int i=0;i<sz;++i)
if(!val[i])
{
for(int j=0;j<CH;++j)
if(!val[ch[i][j]])
{
a.m[i][ch[i][j]]++;
}
}
}
char str[100];
int main ()
{
// initialize
memset(ch[0],0,sizeof(ch[0]));
sz=1;
// 压缩sigma_size
sw['A']=0;sw['G']=1;sw['T']=2;sw['C']=3;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;++i)
{
scanf("%s",str);
_insert(str);
}
getfail();
matrix a(sz),res(sz);
for(int i=0;i<sz;++i)
res.m[i][i]=1;
getmatrix(a);
while(n)
{
if(n&1) res=res*a;
n>>=1;
a=a*a;
}
ll ans=0;
for(int i=0;i<sz;++i)
{
ans+=res.m[0][i];
if(ans>=mod) ans%=mod;
}
cout<<ans<<endl;
return 0;
}