首页 > 技术文章 > AC自动机

Rlemon 2013-09-22 02:40 原文

 

hdu 4758

题意:求长度为n+m,有n个0,且必须包含串s1和s2的串的个数,s1和s2可以重叠;

太久没写AC了,导致比赛的时候很裸的AC自动机的题目都没有往那边想,唉~

比赛的时候就想到状态dp[i][4],但是发现在某一时候在末尾加入s1后会把s2也引入,就是状态转移想不清楚;然后就没有然后了;

AC自动机,通过建AC自动机,得出在任何一个状态下s1,s2出现的情况记录在val[]里,这样用dp[len][i][n][state]状态(表示长度为len的串,最后一个字符在AC自动机里的结点I位,0的个数为n,s1,s2的出现情况的个数)就可以DP了;

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<vector>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<iostream>
  8 #include<queue>
  9 using namespace std;
 10 typedef long long LL;
 11 const int maxnode = 200+10;
 12 const int sigma_sz = 2;
 13 const int N = 210;
 14 const int Mod = 1000000007;
 15 int dp[2][maxnode][110][4];
 16 int n,m;
 17 struct AC{
 18     int ch[maxnode][sigma_sz];
 19     int f[maxnode],val[maxnode];
 20     int sz;
 21     queue<int> q;
 22     void init(){
 23         sz = 1;
 24         memset(ch[0],0,sizeof(ch[0]));
 25         memset(val,0,sizeof(val));
 26     }
 27     int idx(char c) {
 28         if (c == 'R') return 0;
 29         return 1;
 30     }
 31     void insert(char *s,int id) {
 32         int len = strlen(s), u = 0;
 33         for (int i = 0; i < len; i++) {
 34             int c = idx(s[i]);
 35             if (ch[u][c] == 0) {
 36                 memset(ch[sz],0,sizeof(ch[sz]));
 37                 ch[u][c] = sz++;
 38             }
 39             u = ch[u][c];
 40         }
 41         val[u] = id;
 42     }
 43     void getFail(){
 44         while (!q.empty()) q.pop();
 45         for (int i = 0; i < sigma_sz; i++) {
 46             int c = ch[0][i];
 47             if (c)  {
 48                 f[c] = 0; q.push(c);
 49             }
 50         }
 51         while (!q.empty()) {
 52             int u = q.front(); q.pop();
 53             for (int i = 0; i < sigma_sz; i++) {
 54                 int v = ch[u][i];
 55                 if (v) {
 56                     q.push(v);
 57                     int r = f[u];
 58                     while (r && ch[r][i] == 0) r = f[r];
 59                     f[v] = ch[r][i];
 60                     val[v] |= val[f[v]];
 61                 }else {
 62                     ch[u][i] = ch[f[u]][i];
 63                 }
 64             }
 65         }
 66     }
 67     void solve(){
 68         getFail();
 69         int pos = 0;
 70         dp[pos][0][0][0] = 1;
 71         for (int i = 0 ; i < n+m; i++) {
 72             for (int j = 0; j < sz; j++){
 73                 for (int x = 0; x <= i; x++) {
 74                     for (int y = 0; y <= 3; y++) {
 75                         for (int k = 0; k < sigma_sz; k++) {
 76                             int c = ch[j][k];
 77                             int f = (k == 0 ? 1 : 0);
 78                             dp[pos^1][c][x+f][y|val[c]] += dp[pos][j][x][y];
 79                             dp[pos^1][c][x+f][y|val[c]] %= Mod;
 80                         }
 81                     }
 82                 }
 83             }
 84             memset(dp[pos],0,sizeof(dp[pos]));
 85             pos ^= 1;
 86         }
 87         LL ret = 0;
 88         for (int i = 0; i < sz; i++) {
 89             ret = (ret + dp[pos][i][n][3]) % Mod;
 90         }
 91         printf("%lld\n",ret);
 92     }
 93 
 94 }H;
 95 char s[110];
 96 void solve(){
 97     memset(dp,0,sizeof(dp));
 98     H.solve();
 99 }
100 int main(){
101     int T; scanf("%d",&T);
102     while (T--) {
103         scanf("%d%d",&n,&m);
104         H.init();
105         for (int i = 0; i < 2; i++) {
106             scanf("%s",s);
107             H.insert(s,1<<i);
108         }
109         solve();
110     }
111     return 0;
112 }
View Code

 

 UVALive 3942

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<vector>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 const int N = 300000+10;
 10 const int maxnode = 400000+10;
 11 const int sigma_sz = 26;
 12 const int Mod = 20071027;
 13 int dp[N];
 14 struct AC{
 15     int ch[maxnode][sigma_sz];
 16     int sz;
 17     queue<int> q;
 18     int val[maxnode], le[maxnode], last[maxnode], f[maxnode];//le[] > 0 is ends
 19     void init(){
 20         sz = 1;
 21         memset(val,0,sizeof(val));
 22         memset(le,0,sizeof(le));
 23         memset(ch[0],0,sizeof(ch[0]));
 24     }
 25     int idx(char c) {
 26         return c - 'a';
 27     }
 28     void insert(char *s) {
 29         int len = strlen(s), u = 0;
 30         for (int i = 0; i < len; i++) {
 31             int v = idx(s[i]);
 32             if (ch[u][v] == 0) {
 33                 memset(ch[sz],0,sizeof(ch[sz]));
 34                 ch[u][v] = sz++;
 35             }
 36             u = ch[u][v];
 37         }
 38         val[u] = 1;
 39         le[u] = len;
 40     }
 41     void getFail() {
 42         while (!q.empty()) q.pop();
 43         for (int i = 0; i < sigma_sz; i++) {
 44             int v = ch[0][i];
 45             if (v) {
 46                 q.push(v); f[v] = 0; last[v] = 0;
 47             }
 48         }
 49         while (!q.empty()) {
 50             int u = q.front(); q.pop();
 51             for (int i = 0; i < sigma_sz; i++) {
 52                 int v = ch[u][i];
 53                 if (v) {
 54                     q.push(v);
 55                     int r = f[u];
 56                     while (r && ch[r][i] == 0) r = f[r];
 57                     f[v] = ch[r][i];
 58                     val[v] |= val[f[v]];
 59                     last[v] = le[f[v]] ? f[v] : last[f[v]];
 60                 }else {
 61                     ch[u][i] = ch[f[u]][i];
 62                 }
 63             }
 64         }
 65     }
 66     void solve(char *T){
 67         int len = strlen(T);
 68         int u = 0;
 69         for (int i = 1; i < len; i++) {
 70             int c = idx(T[i]);
 71             int r = ch[u][c];
 72             if (val[r]) {
 73                 int j = r;
 74                 while (j) {
 75                     if (le[j]) dp[i] = (dp[i] + dp[i - le[j]] ) % Mod;
 76                     j = last[j];
 77                 }
 78 
 79             }
 80             u = ch[u][c];
 81         }
 82     }
 83 }H;
 84 int n;
 85 char text[N],p[N];
 86 void solve(){
 87     memset(dp,0,sizeof(dp));
 88     dp[0] = 1;
 89     H.solve(text);
 90     printf("%d\n",dp[strlen(text)-1]);
 91 }
 92 int main(){
 93     int cas = 0;
 94     text[0] = '#';
 95     while (~scanf("%s",text+1)) {
 96         scanf("%d",&n);
 97         H.init();
 98         for (int i = 0; i < n; i++) {
 99             scanf("%s",p);
100             H.insert(p);
101         }
102         H.getFail();
103         printf("Case %d: ",++cas);
104         solve();
105     }
106     return 0;
107 }
108 /*
109 abcd
110 4
111 a
112 b
113 cd
114 ab
115 heshehishers
116 7
117 s
118 h
119 e
120 he
121 she
122 his
123 hers
124 
125 */
View Code

 

UALive 4670

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<vector>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<queue>
  8 using namespace std;
  9 const int maxnode = 15000+10;
 10 const int sigma_sz = 26;
 11 const int N = 1000000+10;
 12 int cnt[N];
 13 struct AC{
 14     int ch[maxnode][sigma_sz];
 15     int f[maxnode],val[maxnode],isend[maxnode],last[maxnode];
 16     int sz;
 17     queue<int> q;
 18     void init(){
 19         sz = 1;
 20         memset(val,0,sizeof(val));
 21         memset(isend,0,sizeof(isend));
 22         memset(ch[0],0,sizeof(ch[0]));
 23     }
 24     int idx(char c) {
 25         return c - 'a';
 26     }
 27     void insert(char *s,int id){
 28         int len = strlen(s), u = 0;
 29         for (int i = 0; i < len; i++) {
 30             int c = idx(s[i]);
 31             if (ch[u][c] == 0) {
 32                 memset(ch[sz],0,sizeof(ch[sz]));
 33                 ch[u][c] = sz++;
 34             }
 35             u = ch[u][c];
 36         }
 37         val[u] = 1; isend[u] = id;
 38     }
 39     void getFail(){
 40         while (!q.empty()) q.pop();
 41         for (int i = 0; i < sigma_sz; i++) {
 42             int c = ch[0][i];
 43             if (c) {
 44                 f[c] = 0; last[c] = 0; q.push(c);
 45             }
 46         }
 47         while (!q.empty()) {
 48             int u = q.front(); q.pop();
 49             for (int i = 0; i < sigma_sz; i++) {
 50                 int v = ch[u][i];
 51                 if (v) {
 52                     q.push(v);
 53                     int r = f[u];
 54                     while (r && ch[r][i] == 0) r = f[r];
 55                     f[v] = ch[r][i];
 56                     val[v] |= val[f[v]];
 57                     last[v] = isend[f[v]] ? f[v] : last[f[v]];
 58                 }else {
 59                     ch[u][i] = ch[f[u]][i];
 60                 }
 61             }
 62         }
 63     }
 64     void solve(char *T){
 65         getFail();
 66         int len = strlen(T), u = 0;
 67         for (int i = 0; i < len; i++) {
 68             int c = idx(T[i]);
 69             u = ch[u][c];
 70             int j = u;
 71             if (val[j]) {
 72                 while (j) {
 73                     if (isend[j]) cnt[isend[j]]++;
 74                     j = last[j];
 75                 }
 76             }
 77         }
 78     }
 79 }H;
 80 int n;
 81 char text[N],p[200][80];
 82 void solve(){
 83     H.solve(text);
 84 
 85     int mx = 0;
 86     for (int i = 1; i <= n; i++) {
 87         if (cnt[i] > mx) mx = cnt[i];
 88     }
 89     printf("%d\n",mx);
 90     for (int i = 1 ; i <= n; i++) {
 91         if (cnt[i] == mx) printf("%s\n",p[i]);
 92     }
 93 
 94 }
 95 int main(){
 96     while (~scanf("%d",&n),n) {
 97         memset(cnt,0,sizeof(cnt));
 98         H.init();
 99         for (int i = 1 ; i <= n; i++) {
100             scanf("%s",p[i]);
101            // cout<<p[i]<<endl;
102             H.insert(p[i],i);
103         }
104         scanf("%s",text);
105         solve();
106     }
107     return 0;
108 }
View Code

 

推荐阅读