1. 程式人生 > >POJ 2778 DNA Sequence(AC自動機+矩陣快速冪)

POJ 2778 DNA Sequence(AC自動機+矩陣快速冪)

ace str etc cto .org empty pan dac http

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自動機+矩陣快速冪)