后缀自动机五·重复旋律8

 
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn = 100010;
  4 
  5 char s[maxn], p[maxn<<1];
  6 int maxlen[maxn<<1], minlen[maxn<<1], tr[maxn<<1][26], link[maxn<<1];
  7 int green[maxn<<1], ind[maxn<<1];
  8 int sz;
  9 int news(int maxl, int minl, int *trans, int lk){
 10     link[sz] = lk; maxlen[sz] = maxl, minlen[sz] = minl;
 11     for(int i = 0; i < 26; i++) 
 12         if(trans == NULL) tr[sz][i] = -1;
 13         else tr[sz][i] = trans[i];
 14     return sz++; 
 15 }
 16 
 17 int add(int c, int u){
 18     c = c - 'a';
 19     int z = news(maxlen[u] + 1, -1, NULL, -1);
 20     green[z] = 1;
 21     int v = u;
 22     while(v != -1 && tr[v][c] == -1){
 23         tr[v][c] = z;
 24         v = link[v];
 25     }
 26     if(v == -1) {
 27         minlen[z] = 1;
 28         link[z] = 0;
 29         ind[0]++;
 30         return z;
 31     }
 32     int x =  tr[v][c];
 33     if(maxlen[x] == maxlen[v] + 1) {
 34         link[z] = x;
 35         ind[x]++;
 36         minlen[z] = maxlen[x] + 1;
 37         return z;
 38     }
 39     int y = news(maxlen[v] + 1, -1, tr[x], link[x]);
 40     minlen[x] = minlen[z] = maxlen[y] + 1;
 41     minlen[y] = maxlen[link[y]] + 1;
 42     link[x] = link[z] = y;
 43     ind[y] += 2;
 44     int w = v;
 45     while(w != -1 && tr[w][c] == x){
 46         tr[w][c] = y;
 47         w = link[w];
 48     }
 49     return z;
 50 }
 51 int cnt[maxn<<1];
 52 void get_cnt(){
 53     queue<int> q;
 54     for(int i = 0; i < sz; i++) if(ind[i] == 0) q.push(i);
 55     while(!q.empty()){
 56         int u = q.front(); q.pop();
 57         if(green[u]) cnt[u]++;
 58         cnt[link[u]] += cnt[u];
 59         if(--ind[link[u]] == 0) q.push(link[u]);
 60     }
 61 }
 62 int vis[maxn<<1];
 63 int solve(char *p){
 64     memset(vis, 0, sizeof vis);
 65     int ls = strlen(p);
 66     int len = ls / 2 + 1;
 67     int res = 0;
 68     int u = 0, l = 0;
 69     for(int i = 0; i < ls; i++){
 70         int c = p[i] - 'a';
 71         while(u && tr[u][c] == -1){
 72             u = link[u];
 73             l = maxlen[u];
 74         }
 75         if(tr[u][c] != -1){
 76             u = tr[u][c];
 77             l++;
 78         }else{
 79             u = 0; l = 0;
 80         }
 81         if(l > len){
 82             while(maxlen[link[u]] >= len){
 83                 u = link[u]; 
 84                 l = maxlen[u];
 85             }
 86         }
 87         if(l >= len && !vis[u]){
 88             vis[u] = 1;
 89             res += cnt[u];
 90         }
 91     }
 92     return res;
 93 }
 94 int main(){
 95     int n;
 96     while(scanf("%s", s) != EOF){
 97         memset(ind, 0, sizeof ind);
 98         memset(cnt, 0, sizeof cnt);
 99         memset(green, 0, sizeof green);
100         sz = 0;
101         int pre = news(0, 0, NULL, -1);
102         int len = strlen(s);
103         for(int i = 0; i < len; i++) {
104             pre = add(s[i], pre);
105         }
106         get_cnt();
107         scanf("%d", &n);
108         for(int i = 0; i < n; i++){
109             scanf("%s", p);
110             len = strlen(p);
111             int len2 = len * 2 - 1;
112             for(int j = len; j < len2; j++){
113                 p[j] = p[j - len];
114             }
115             p[len2] = '\0';
116             printf("%d\n", solve(p));
117         }
118     }
119     return 0;
120 }
View Code

 

posted @ 2018-03-06 19:35  yijiull  阅读(207)  评论(0编辑  收藏  举报