DNA Sequence POJ - 2778 (ac自动机)

DNA Sequence

 POJ - 2778 

题意:

昨天看了好久也没明白咋回事。。。今天忽然就理解了。。。

晚上再来补题解。。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 using namespace std;
  6 #define CLR(m,a) memset(m,a,sizeof(m))
  7 #define LL long long
  8 const int mod=100000;
  9 const int maxnode=100;
 10 const int sigma=4;
 11 
 12 //矩阵
 13 struct Matrix
 14 {
 15     int n;
 16     int m[maxnode][maxnode];
 17     void init(int sz)
 18     {
 19         n=sz;
 20         CLR(m,0);
 21     }
 22     Matrix(int sz){init(sz);}
 23     void setE()
 24     {
 25         for(int i=0;i<n;i++) m[i][i]=1;
 26     }
 27     Matrix operator*(const Matrix &temp)
 28     {
 29         Matrix ans(n);
 30         for(int k=0;k<n;k++)
 31             for(int i=0;i<n;i++)
 32                 for(int j=0;j<n;j++)
 33                     ans.m[i][j]=(ans.m[i][j]+(LL)m[i][k]*temp.m[k][j]%mod)%mod;
 34         return ans;
 35     }
 36 
 37 };
 38 void quickpow(Matrix &base,Matrix &ans,int e)
 39 {
 40     ans.setE();//
 41     while(e){
 42         if(e&1) ans=ans*base;
 43         e>>=1;
 44         base=base*base;
 45     }
 46 }
 47 //AC自动机
 48 struct AC
 49 {
 50     int ch[maxnode][sigma],f[maxnode];
 51     int match[maxnode];
 52     int sz;
 53 
 54     void init()
 55     {
 56         CLR(ch[0],0);
 57         CLR(match,0);
 58         sz=1;
 59     }
 60     int idx(char c)
 61     {
 62         switch(c)
 63         {
 64             case 'A': return 0;
 65             case 'T': return 1;
 66             case 'G': return 2;
 67             case 'C': return 3;
 68         }
 69     }
 70 
 71     void inser(char *s)
 72     {
 73         int u=0,n=strlen(s);
 74         for(int i=0;i<n;i++){
 75             int c=idx(s[i]);
 76             if(!ch[u][c]){
 77                 CLR(ch[sz],0);
 78                 ch[u][c]=sz++;
 79             }
 80             u=ch[u][c];
 81         }
 82         match[u]=1;
 83     }
 84     void getfail()
 85     {
 86         queue<int> q;
 87         f[0]=0;
 88         match[0]=0;
 89         for(int c=0;c<sigma;c++){
 90             int u=ch[0][c];
 91             if(u) {
 92                 q.push(u);
 93                 f[u]=0;
 94             }
 95         }
 96         while(!q.empty()){
 97             int r=q.front();
 98             q.pop();
 99             for(int c=0;c<sigma;c++){
100                 int u=ch[r][c];
101                 if(!u) { ch[r][c]=ch[f[r]][c]; continue; }  //
102                 q.push(u);
103                 int v=f[r];
104                 while(v&&!ch[v][c]) v=f[v];  //
105                 f[u]=ch[v][c];
106                 match[u]|=match[f[u]];
107             }
108         }
109     }
110     int solve(int m)
111     {
112         Matrix a(sz),b(sz);
113         for(int i=0;i<sz;i++)
114         for(int j=0;j<sigma;j++){
115             if(match[i]||match[ch[i][j]]) continue;   //
116             a.m[i][ch[i][j]]++;
117         }
118         quickpow(a,b,m);
119         int ans=0;
120         for(int i=0;i<sz;i++){
121             ans=(ans+b.m[0][i])%mod;
122         }
123         return ans;
124     }
125 };
126 AC ac;
127 int main()
128 {
129     int n,m;
130     while(scanf("%d%d",&n,&m)!=EOF){
131         ac.init();
132         char s[11];
133         for(int i=0;i<n;i++){
134             scanf("%s",s);
135             ac.inser(s);
136         }
137         ac.getfail();
138         printf("%d\n",ac.solve(m));
139     }
140 }
View Code

发现少模一次速度快了将近一倍。。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 using namespace std;
  6 #define CLR(m,a) memset(m,a,sizeof(m))
  7 #define LL long long
  8 const int mod=100000;
  9 const int maxnode=110;
 10 const int sigma=4;
 11 
 12 struct Matrix
 13 {
 14     int n;
 15     int m[maxnode][maxnode];
 16     void init(int sz)
 17     {
 18         n=sz;
 19         CLR(m,0);
 20     }
 21     Matrix(int sz){init(sz);}
 22     void setE()
 23     {
 24         for(int i=0;i<n;i++) m[i][i]=1;
 25     }
 26     Matrix operator*(const Matrix &temp)
 27     {
 28         Matrix ans(n);
 29         for(int k=0;k<n;k++)
 30             for(int i=0;i<n;i++)
 31                 for(int j=0;j<n;j++)
 32                     ans.m[i][j]=(ans.m[i][j]+(LL)m[i][k]*temp.m[k][j])%mod;
 33         return ans;
 34     }
 35 
 36 };
 37 void quickpow(Matrix &base,Matrix &ans,int e)
 38 {
 39     ans.setE();//
 40     while(e){
 41         if(e&1) ans=ans*base;
 42         e>>=1;
 43         base=base*base;
 44     }
 45 }
 46 struct AC
 47 {
 48     int ch[maxnode][sigma],f[maxnode];
 49     int match[maxnode];
 50     int sz;
 51 
 52     void init()
 53     {
 54         CLR(ch[0],0);
 55         CLR(match,0);
 56         sz=1;
 57     }
 58     int idx(char c)
 59     {
 60         switch(c)
 61         {
 62             case 'A': return 0;
 63             case 'T': return 1;
 64             case 'G': return 2;
 65             case 'C': return 3;
 66         }
 67     }
 68 
 69     void inser(char *s)
 70     {
 71         int u=0,n=strlen(s);
 72         for(int i=0;i<n;i++){
 73             int c=idx(s[i]);
 74             if(!ch[u][c]){
 75                 CLR(ch[sz],0);
 76                 ch[u][c]=sz++;
 77             }
 78             u=ch[u][c];
 79         }
 80         match[u]=1;
 81     }
 82     void getfail()
 83     {
 84         queue<int> q;
 85         f[0]=0;
 86         match[0]=0;
 87         for(int c=0;c<sigma;c++){
 88             int u=ch[0][c];
 89             if(u) {
 90                 q.push(u);
 91                 f[u]=0;
 92             }
 93         }
 94         while(!q.empty()){
 95             int r=q.front();
 96             q.pop();
 97             for(int c=0;c<sigma;c++){
 98                 int u=ch[r][c];
 99                 if(!u) { ch[r][c]=ch[f[r]][c]; continue; }  //
100                 q.push(u);
101                 int v=f[r];
102                 while(v&&!ch[v][c]) v=f[v];  //
103                 f[u]=ch[v][c];
104                 match[u]|=match[f[u]];
105             }
106         }
107     }
108     int solve(int m)
109     {
110         Matrix a(sz),b(sz);
111         for(int i=0;i<sz;i++)
112         for(int j=0;j<sigma;j++){
113             if(match[i]||match[ch[i][j]]) continue;
114             a.m[i][ch[i][j]]++;
115         }
116         quickpow(a,b,m);
117         int ans=0;
118         for(int i=0;i<sz;i++){
119             ans=(ans+b.m[0][i])%mod;
120         }
121         return ans;
122     }
123 };
124 AC ac;
125 int main()
126 {
127     int n,m;
128     while(scanf("%d%d",&n,&m)!=EOF){
129         ac.init();
130         char s[15];
131         for(int i=0;i<n;i++){
132             scanf("%s",s);
133             ac.inser(s);
134         }
135         ac.getfail();
136         printf("%d\n",ac.solve(m));
137     }
138 }
View Code

 

posted @ 2017-08-18 10:51  yijiull  阅读(155)  评论(0编辑  收藏  举报