poj 2778 DNA Sequence
和poj 1625一样,不同的是长度变长了
先考虑另外一个问题,给你一个有向图,从某个点出发走n步到其他任意点,问不同的走法。
对这个问题构造一个矩阵,matrix[i][j]表示从i到j有几条边,然后这个矩阵自乘n次就是答案。
再说这个问题, Trie图本身就是一个有向图,那么一个长度为n的字符串相当于从根节点沿着边走n步。。。所以和上面那个问题一样。。构造矩阵的时候要注意边不能有非法节点。
可以在构造矩阵时去掉非法节点的行和列来优化。。(这里我没去掉。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const int N = 110; 8 const int mod = (int)1e5; 9 int top; 10 struct Matrix{ 11 ll d[N][N]; 12 Matrix(int r = 0){ 13 memset(d,0,sizeof(d)); 14 if(r){ 15 for(int i = 0;i < top;i++) 16 d[i][i] = 1; 17 } 18 } 19 Matrix operator *(const Matrix &a){ 20 Matrix ans; 21 for(int k = 0;k < top;k++) 22 for(int i = 0;i < top;i++) 23 for(int j = 0;j < top;j++) 24 ans.d[i][j] = (ans.d[i][j] + d[i][k] * a.d[k][j]) % mod; 25 return ans; 26 } 27 }; 28 struct node{ 29 node *ch[4],*fail; 30 bool flag; 31 void clear(){ 32 for(int i = 0;i < 4;i++)ch[i] = NULL;fail = NULL; 33 flag = 0; 34 } 35 }; 36 int hash[129]; 37 node stk[N*N]; 38 struct Trie{ 39 node *root; 40 node* newnode(){ 41 node *p = &stk[top++]; 42 p -> clear(); 43 return p; 44 } 45 void init(){ 46 top = 0; 47 root = newnode(); 48 } 49 void insert(char *s){ 50 node *p = root;int len = strlen(s); 51 for(int i = 0; i < len ;i++){ 52 int id = hash[s[i]]; 53 if(p -> ch[id] == NULL) 54 p -> ch[id] = newnode(); 55 p = p -> ch[id]; 56 } 57 p -> flag = 1; 58 } 59 void build(){ 60 queue<node*> Q; 61 root -> fail = root; 62 for(int i = 0; i < 4;i++) 63 if(root -> ch[i] == NULL) 64 root -> ch[i] = root; 65 else{ 66 Q.push(root -> ch[i]); 67 root -> ch[i] -> fail = root; 68 } 69 while(!Q.empty()){ 70 node *p = Q.front();Q.pop(); 71 for(int i = 0;i < 4;i++) 72 if(p -> ch[i] == NULL) 73 p -> ch[i] = p -> fail -> ch[i]; 74 else{ 75 Q.push(p -> ch[i]); 76 p -> ch[i] -> fail = p -> fail -> ch[i]; 77 p -> ch[i] -> flag |= p -> ch[i] -> fail -> flag; 78 } 79 } 80 } 81 Matrix getMatrix(){ 82 Matrix ans; 83 for(int i = 0;i < top;i++){ 84 node *cur = &stk[i]; 85 if(cur -> flag)continue; 86 for(int j = 0;j < 4;j++){ 87 node *next = cur -> ch[j]; 88 if(next -> flag)continue; 89 ans.d[i][next - stk]++; 90 } 91 } 92 return ans; 93 } 94 }; 95 Matrix Pow(Matrix E,int n){ 96 Matrix ans(1); 97 while(n){ 98 if(n&1)ans = ans * E; 99 E = E * E; 100 n >>= 1; 101 } 102 return ans; 103 } 104 Trie AC; 105 int main(){ 106 hash['A'] = 0;hash['C'] = 1;hash['G'] = 2;hash['T'] = 3; 107 int m,n; 108 while(~scanf("%d%d",&m,&n)){ 109 AC.init(); 110 for(int i = 1;i <= m;i++){ 111 char s[20]; 112 scanf("%s",s); 113 AC.insert(s); 114 } 115 AC.build(); 116 Matrix E = AC.getMatrix(); 117 Matrix ans = Pow(E,n); 118 int number = 0; 119 for(int i = 0;i < top;i++){ 120 number += ans.d[0][i]; 121 number %= mod; 122 } 123 printf("%d\n",number); 124 } 125 return 0; 126 }