标签:
http://poj.org/problem?id=2778
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 14470 | Accepted: 5579 |
Description
Input
Output
Sample Input
4 3 AT AC AG AA
Sample Output
36
问题大意:长度为n 由’A’‘G’‘C’‘T‘组成的字符串中不包含这m个字符串的任意一个的组合有多少种;
标记每个字符串的结尾节点为危险节点,如果失败后跳转到的节点是危险节点那么该节点也应为危险节点。
问题转化为长度问n不经过危险节点的走法有多少种。
构造矩阵mat,mat[i][j]为从第i个节点走一步到达第j个节点有多少种走法。求下mat的n次方,即求得ans[][],ans[i][j]为第i个节点走n步到达第j个节点的走法有多少种。
求下ans[0][i]的和就好。
理解好ac自动机和矩阵的含义后还是很好理解的。
后台数据比题意的数据要大一些。一开始一直wa,改了范围就A了。
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define maxx(a,b) ((a)>(b)?(a):(b))
#define F first
#define S second
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int mod = 100000;
const LL inf=0x3f3f3f3f;
//const double pi=acos(-1);
const int N=210;//最大点数
const int M=130;// 最大边数
int ans;
int bl[500];
struct mat
{
int v[210][210];
};
mat c,an;
int size_mat;
mat matrix_mul(mat p1,mat p2,int n,int m,int q)
{
mat t;
memset(t.v,0,sizeof(t.v));
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(p1.v[i][j])
for(int k=0; k<q; k++)
{
int tep=((long long )p1.v[i][j]*p2.v[j][k])%mod;
t.v[i][k]=(t.v[i][k]+tep)%mod;
}
return t;
}
mat matrix_mi(mat p,int n,int k)
{
mat t;
memset(t.v,0,sizeof(t.v));
for(int i=0; i<n; i++)
{
t.v[i][i]=1;
}
while(k)
{
if(k&1)
t=matrix_mul(t,p,n,n,n);
k>>=1;
p=matrix_mul(p,p,n,n,n);
}
return t;
}
struct Trie
{
int next[N][4],fail[N],end[N];
int root,L;
int nownode()
{
for(int i=0; i<4; i++)
next[L][i]=-1;
end[L++]=0;
return L-1;
}
void init()
{
L=0;
root=nownode();
}
void insert(char buf[],int k)
{
int len=strlen(buf);
int now=root;
for(int i=0; i<len; i++)
{
if(next[now][bl[buf[i]]]==-1)
next[now][bl[buf[i]]]=nownode();
now=next[now][bl[buf[i]]];
}
end[now]=1;
}
void build()
{
queue<int>Q;
fail[root]=root;
for(int i=0; i<4; i++)
if(next[root][i]==-1)
next[root][i]=root;
else
{
fail[next[root][i]]=root;
Q.push(next[root][i]);
}
while(!Q.empty())
{
int now=Q.front();
Q.pop();
if(end[fail[now]]==1)
end[now]=1;
for(int i=0; i<4; i++)
{
if(next[now][i]==-1)
next[now][i]=next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
int gett()
{
for(int i=0; i<L; i++)
{
for(int j=0; j<4; j++)
{
if(end[next[i][j]]==0)
c.v[i][next[i][j]]++;
}
}
return L;
}
};
Trie ac;
char str[500];
int main()
{
#ifdef LOCAL
freopen("date.in","r",stdin);
freopen("date.out","w",stdout);
#endif
int m,n;
bl['A']=0;
bl['G']=1;
bl['C']=2;
bl['T']=3;
while(scanf("%d%d",&m,&n)!=EOF)
{
ac.init();
for(int i=1; i<=m; i++)
{
scanf("%s",str);
ac.insert(str,i);
}
ac.build();
memset(c.v,0,sizeof(c.v));
size_mat=ac.gett();
an=matrix_mi(c,size_mat,n);
ans=0;
// for(int i=0;i<size_mat;i++)
// {
// puts("");
// for(int j=0;j<size_mat;j++)
// printf("%d ",an.v[i][j]);
// }
for(int i=0;i<size_mat;i++)
{
ans+=an.v[0][i];
ans%=mod;
}
printf("%d\n",ans);
}
return 0;
}
poj 2778 DNA Sequence ac自动机+矩阵快速幂
标签:
原文地址:http://blog.csdn.net/hfengzhi/article/details/51354729