题目链接:http://poj.org/problem?id=2778
题目大意:问长度为N的串中不包含了模式串的串有几个。
题目思路:求长度为n的不含病毒串的字符串个数,用ac自动机构造转移矩阵,再用二分幂计算即可。需要注意的是尽量不用模运算,模运算实在是太慢了。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110
#define mod 100000
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int q[12*12];
int a[120][120],b[120][120];
__int64 c[120][120];
int cnt;
char s[12];
int ans;
int mp[256];
int hash[200];
struct node
{
int cnt,fail;
int next[4];
void init()
{
cnt=fail=0;
memset(next,0,sizeof(next));
}
}tri[12*12];
void insert(char *s)
{
int p,x,i;
p=0;
for(i=0;s[i];i++)
{
x=mp[s[i]];
if(!tri[p].next[x])
{
tri[++cnt].init();
tri[p].next[x]=cnt;
}
p=tri[p].next[x];
}
tri[p].cnt++;
}
void bfs()
{
int i,p,suf,head=0,tail=0;
p=0;
for(i=0;i<4;i++)
{
if(tri[0].next[i])
{
q[tail++]=tri[0].next[i];
tri[q[tail-1]].fail=0;
}
}
while(head<tail)
{
p=q[head++];suf=tri[p].fail;
if(tri[suf].cnt)
tri[p].cnt=1;
for(i=0;i<4;i++)
{
if(tri[p].next[i])
{
q[tail++]=tri[p].next[i];
tri[q[tail-1]].fail=tri[suf].next[i];
}
else
tri[p].next[i]=tri[suf].next[i];
}
}
memset(b,0,sizeof(b));
int rec=0;
for(i=0;i<=cnt;i++)
{
if(!tri[i].cnt)
hash[i]=rec++;
}
for(i=0;i<=cnt;i++)
{
if(tri[i].cnt)
continue;
for(int j=0;j<4;j++)
{
int tmp=tri[i].next[j];
if(!tri[tmp].cnt)
b[hash[i]][hash[tmp]]++;
}
}
cnt=rec-1;
}
inline void run(int a[][120],int b[][120],__int64 c[][120])
{
int i,j,k;
for(i=0;i<=cnt;i++)
for(j=0;j<=cnt;j++)
{
c[i][j]=0;
for(k=0;k<=cnt;k++)
c[i][j]+=((__int64)a[i][k]*b[k][j]);
c[i][j]%=mod;
}
for(i=0;i<=cnt;i++)
for(j=0;j<=cnt;j++)
a[i][j]=c[i][j];
}
void solve(int n)
{
memset(a,0,sizeof(a));
a[0][0]=1;
while(n)
{
if(n&1)
run(a,b,c);
n>>=1;
run(b,b,c);
};
for(int i=0;i<=cnt;i++)
ans+=a[0][i];
ans%=mod;
}
int main()
{
int m,n;
mp['A']=0;mp['C']=1;mp['G']=2;mp['T']=3;
while(scanf("%d%d",&m,&n)!=EOF)
{
ans=0;
cnt=0;
tri[0].init();
while(m--)
{
scanf("%s",s);
insert(s);
}
bfs();
solve(n);
printf("%d\n",ans);
}
}