后缀自动机五·重复旋律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 }