POJ 2778 DNA Sequence (AC自动机,矩阵乘法)

题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种。

思路:用AC自动机,利用AC自动机上的节点做矩阵乘法。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<string>
  6 #include<algorithm>
  7 #include<queue>
  8 #define MOD 100000
  9 char s[2005];
 10 int ch(char x){
 11     if (x=='A') return 0;
 12     if (x=='C') return 1;
 13     if (x=='G') return 2;
 14     if (x=='T') return 3;
 15     return -1;
 16 }
 17 struct Trie{
 18     int fail[1005],next[1005][5],end[1005],L,root;
 19     int newnode(){
 20         for (int i=0;i<4;i++)
 21          next[L][i]=-1;
 22         end[L++]=-1;
 23         return L-1; 
 24     }
 25     void clear(){
 26          L=0;
 27          root=newnode();
 28     }
 29     void insert(char s[]){
 30         int len=strlen(s),now=root;
 31         for (int i=0;i<len;i++){
 32             if (next[now][ch(s[i])]==-1) next[now][ch(s[i])]=newnode();
 33             now=next[now][ch(s[i])];
 34         }
 35         end[now]=1;
 36     }
 37     void build(){
 38         std::queue<int>Q;
 39         int now;
 40         for (int i=0;i<4;i++)
 41          if (next[root][i]==-1)
 42           next[root][i]=root;
 43          else{
 44           fail[next[root][i]]=root;
 45           Q.push(next[root][i]);
 46          } 
 47         while (!Q.empty()){
 48             now=Q.front();Q.pop();
 49             if (end[fail[now]]==1) end[now]=1;
 50             for (int i=0;i<4;i++){
 51                 if (next[now][i]==-1) next[now][i]=next[fail[now]][i];
 52                 else{
 53                     fail[next[now][i]]=next[fail[now]][i];
 54                     Q.push(next[now][i]);
 55                 }
 56             }
 57         } 
 58     }
 59 }ac;
 60 struct Matrix{
 61     int n,mx[105][105];
 62     Matrix(){}
 63     Matrix(int x){
 64         n=x;
 65         for (int i=0;i<n;i++)
 66          for (int j=0;j<n;j++)
 67           mx[i][j]=0;
 68     }    
 69 };
 70 Matrix operator *(Matrix a,Matrix b){
 71     int n=a.n;
 72     Matrix c=Matrix(n);
 73     for (int i=0;i<n;i++)
 74      for (int j=0;j<n;j++)
 75       for (int k=0;k<n;k++){
 76           int tmp=(long long) a.mx[i][k]*b.mx[k][j]%MOD;
 77           c.mx[i][j]=(c.mx[i][j]+tmp)%MOD;
 78       }
 79     return c;   
 80 } 
 81 Matrix powm(Matrix t,int m){
 82     Matrix r=Matrix(t.n);
 83     for (int i=0;i<=t.n;i++)
 84      r.mx[i][i]=1;
 85     while (m){
 86         if (m%2) r=r*t;
 87         t=t*t;
 88         m/=2;
 89     }
 90     return r;
 91 }
 92 int main(){
 93     int m;
 94     int n;
 95     while (scanf("%d%d",&n,&m)!=EOF){
 96         ac.clear();
 97         for (int i=0;i<n;i++){
 98             scanf("%s",s);
 99             ac.insert(s);
100         }
101         ac.build();
102         Matrix a=Matrix(ac.L);
103         for (int i=0;i<ac.L;i++)
104           for (int j=0;j<4;j++)
105             if (ac.end[ac.next[i][j]]==-1)
106                 a.mx[i][ac.next[i][j]]++;
107         a=powm(a,m);
108         int ans=0;
109         for (int i=0;i<a.n;i++)
110          ans=(ans+a.mx[0][i])%MOD;
111         printf("%d
",ans); 
112     }
113 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5551741.html