题意:给出n个字串表示“缺陷基因”,然后让求长度为m的基因(4^m个)中有多少个不带病。
题解:首先建立AC自动机,然后从每个节点开始选“ATGC”有四种往外转移的途径。
如:ACG,C这两个基因建一个ACauto,然后转移矩阵为下。
2 1 0 0 1
2 1 1 0 0
1 1 0 1 1
2 1 0 0 1
2 1 0 0 1
然后把危险状态删去(赋0),即基因结束节点的行和列。
然后矩阵变成
2 1 0 0 0
2 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
即
2 1
2 1
然后做矩阵乘法得出答案!
/*poj2778*/
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100
#define M 4
#define MOD 100000
using namespace std;
int next[N][M],fail[N],map[N][N],crs[N],root,cnt,n,m;
bool end[N],danger[N],visit[M];
char t[N];
queue<int>q;
struct mrx
{
long long s[N][N];
}I,O;
mrx mul(mrx a,mrx b)
{
int i,j,k;
mrx c=I;
for(i=0;i<=cnt;i++)
{
for(j=0;j<=cnt;j++)
{
for(k=0;k<=cnt;k++)
{
c.s[i][j]+=a.s[i][k]*b.s[k][j];
}
c.s[i][j]%=MOD;
}
}
return c;
}
mrx power(mrx a,int p)
{
mrx ans=O;
while(p)
{
if(p&1)
{
ans=mul(ans,a);
}
a=mul(a,a);
p>>=1;
}
return ans;
}
void init()
{
root=cnt=0;
memset(fail,0,sizeof(fail));
memset(end,0,sizeof(end));
memset(map,0,sizeof(map));
while(!q.empty())q.pop();
}
void acauto()
{
int i,j,u,v,temp,alp,flag;
scanf("%d%d",&n,&m);
crs['A']=0;
crs['T']=1;
crs['G']=2;
crs['C']=3;
for(i=1;i<=n;i++)/*insert*/
{
scanf("%s",t+1);
for(temp=root,j=1;t[j];j++)
{
alp=crs[t[j]];
if(!next[temp][alp])next[temp][alp]=++cnt;
temp=next[temp][alp];
}
end[temp]=1;
}
q.push(root);/*维护fail指针*/
while(!q.empty())
{
u=q.front();q.pop();
for(i=0;i<M;i++)
{
v=next[u][i];
if(v)
{
if(end[v])danger[v]=1;
if(u==root)fail[v]=root;
else
{
temp=fail[u];
while(temp&&!next[temp][i])temp=fail[temp];
fail[v]=next[temp][i];
if(danger[fail[v]])danger[v]=1;
}
q.push(v);
}
}
}
for(i=0;i<=cnt;i++)
{
temp=i;flag=0;
memset(visit,0,sizeof(visit));
while(temp&&flag<M)
{
for(j=0;j<M;j++)if(!visit[j]&&next[temp][j])
{
map[i][next[temp][j]]++;
visit[j]=1;
flag++;
}
temp=fail[temp];
}
if(flag<M)for(j=0;j<M;j++)if(!visit[j])
{
map[i][next[0][j]]++;
}
}
for(i=0;i<=cnt;i++)if(danger[i])
{
for(j=0;j<=cnt;j++)map[i][j]=map[j][i]=0;
}
}
void handle()
{
int i,j;
mrx P=I;
for(i=0;i<=cnt;i++)O.s[i][i]=1;
for(j=0;j<=cnt;j++)for(i=0;i<=cnt;i++)
{
P.s[i][j]=map[j][i];
}
P=mul(O,power(P,m));
long long ans=0;
for(i=0;i<=cnt;i++)
{
ans+=P.s[i][0];
}
cout<<ans%MOD<<endl;
}
int main()
{
// freopen("test.in","r",stdin);
acauto();
handle();
return 0;
}