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; }