POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)相关的知识,希望对你有一定的参考价值。
http://poj.org/problem?id=2778
题意:
给出一些病毒字符串,只由A,T,C,G组成,现在要用着4个字符组成长度为n的字符串,且字符串中不可以包含任一病毒字符串,问共有多少种字符串。
思路:
回想一下离散数学中所学的邻接矩阵
而AC自动机的状态图就是一个有向图,我们只需要根据这个有向图建立邻接矩阵即可,因为不可以包含病毒串,所以只需要判断是否是字符串结尾,如果不是就说明可以连接起来。
注意在fail转移的时候传递字符串结尾标记。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 const int maxn=10000+5; 15 const int mod=100000; 16 17 int n, m, num; 18 char s[20]; 19 20 struct Trie 21 { 22 int son[10]; 23 int cnt; 24 int fail; 25 }t[150]; 26 27 28 struct Matrix 29 { 30 ll mat[200][200], n; 31 Matrix(){} 32 Matrix(int _n) 33 { 34 n=_n; 35 for(int i=0;i<n;i++) 36 for(int j=0;j<n;j++) 37 mat[i][j]=0; 38 } 39 Matrix operator*(const Matrix& b) const 40 { 41 Matrix c=Matrix(n); 42 for(int i=0;i<n;i++) 43 { 44 for(int j=0;j<n;j++) 45 { 46 for(int k=0;k<n;k++) 47 { 48 c.mat[i][j]=(c.mat[i][j]+mat[i][k]*b.mat[k][j])%mod; 49 } 50 } 51 } 52 return c; 53 } 54 }; 55 56 void init(int x) 57 { 58 t[x].fail=0; 59 t[x].cnt=0; 60 memset(t[x].son,0,sizeof(t[x].son)); 61 } 62 63 int getch(char ch) 64 { 65 if(ch==\'A\') return 1; 66 if(ch==\'T\') return 2; 67 if(ch==\'C\') return 3; 68 if(ch==\'G\') return 4; 69 } 70 71 void trie(char *s) 72 { 73 int n=strlen(s); 74 int x=0; 75 for(int i=0;i<n;i++) 76 { 77 int c=getch(s[i]); 78 if(!t[x].son[c]) 79 { 80 num++; 81 init(num); 82 t[x].son[c]=num; 83 } 84 x=t[x].son[c]; 85 } 86 t[x].cnt=1; 87 } 88 89 void buildAC() 90 { 91 queue<int> Q; 92 for(int i=1;i<=4;i++) if(t[0].son[i]) Q.push(t[0].son[i]); 93 while(!Q.empty()) 94 { 95 int x=Q.front(); Q.pop(); 96 int fail=t[x].fail; 97 for(int i=1;i<=4;i++) 98 { 99 100 int y=t[x].son[i]; 101 if(y) 102 { 103 t[y].fail=t[fail].son[i]; 104 t[y].cnt|=t[t[fail].son[i]].cnt; //这儿很重要,这个标记需要传递 105 Q.push(y); 106 } 107 else t[x].son[i]=t[fail].son[i]; 108 } 109 } 110 } 111 112 Matrix getMatrix() 113 { 114 Matrix c=Matrix(num+1); 115 for(int i=0;i<=num;i++) 116 { 117 for(int j=1;j<=4;j++) 118 { 119 if(t[t[i].son[j]].cnt==0) c.mat[i][t[i].son[j]]++; 120 } 121 } 122 return c; 123 } 124 125 126 void q_pow(Matrix base, int n) 127 { 128 Matrix ans=Matrix(base.n); 129 for(int i=0;i<ans.n;i++) ans.mat[i][i]=1; 130 while(n) 131 { 132 if(n&1) ans=ans*base; 133 base=base*base; 134 n>>=1; 135 } 136 int res=0; 137 for(int i=0;i<ans.n;i++) 138 res=(res+ans.mat[0][i])%mod; 139 printf("%d\\n",res); 140 } 141 142 int main() 143 { 144 //freopen("in.txt","r",stdin); 145 while(~scanf("%d%d",&m,&n)) 146 { 147 init(0); 148 num=0; 149 for(int i=1;i<=m;i++) 150 { 151 scanf("%s",s); 152 trie(s); 153 } 154 buildAC(); 155 Matrix c=getMatrix(); 156 q_pow(c,n); 157 } 158 return 0; 159 }
以上是关于POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2778 DNA Sequence(AC自动机+矩阵)
poj2778 DNA Sequence(AC自动机+矩阵快速幂)
poj2778 DNA Sequence(AC自动机+矩阵快速幂)