DNA Sequence POJ - 2778 (ac自动机)
DNA Sequence
题意:
昨天看了好久也没明白咋回事。。。今天忽然就理解了。。。
晚上再来补题解。。。
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 }
发现少模一次速度快了将近一倍。。。
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 }