题意和思路都和上一篇差不多。
有一个区别就是需要移动字符串。关于这个字符串,可以用3次reverse来转换, 前面部分翻转一下, 后面部分翻转一下, 最后整个串翻转一下就好了。
注意就是多组测试,需要初始化。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const LL mod = (int)1e9+7; 16 const int N = 1e7; 17 struct Node{ 18 static const int m = 2; 19 static const int KN = N; 20 int next[KN][m], fair[KN], tot = 0, mark[KN], mark1[KN], root[20], cnt = 0, si[20]; 21 void init(){ 22 tot = cnt = 0; 23 } 24 int newtree(){ 25 tot++; 26 fair[tot] = mark[tot] = mark1[tot] = 0; 27 memset(next[tot], 0, sizeof(next[tot])); 28 return tot; 29 } 30 void Build(int x){ 31 queue<int> q; 32 q.push(x); 33 int pos, p, v; 34 while(!q.empty()){ 35 pos = q.front(), q.pop(); 36 for(int i = 0; i < m; i++){ 37 if(!next[pos][i]) continue; 38 p = fair[pos]; v = next[pos][i]; 39 while(p && !next[p][i]) p = fair[p]; 40 if(p) fair[v] = next[p][i]; 41 else fair[v] = x; 42 q.push(v); 43 mark1[v] = mark1[fair[v]] + mark[v]; 44 } 45 } 46 } 47 void Add(char s[], char ch){ 48 root[++cnt] = newtree(); si[cnt] = 1; 49 int pos = root[cnt]; 50 for(int i = 0; s[i]; i++){ 51 if(!next[pos][s[i]-ch]) next[pos][s[i]-ch] = newtree(); 52 pos = next[pos][s[i]-ch]; 53 } 54 mark[pos]++; 55 while(si[cnt] == si[cnt-1]){ 56 Unit(root[cnt-1], root[cnt]); 57 si[--cnt] *= 2; 58 } 59 Build(root[cnt]); 60 } 61 int Query(char s[], char ch){ 62 int pos, ret = 0; 63 for(int id = 1; id <= cnt; id++){ 64 pos = root[id]; 65 for(int i = 0; s[i]; i++){ 66 while(pos && !next[pos][s[i]-ch]) pos = fair[pos]; 67 if(pos) pos = next[pos][s[i]-ch]; 68 else pos = root[id]; 69 ret += mark1[pos]; 70 } 71 } 72 return ret; 73 } 74 void Unit(int u, int v){ 75 mark[u] += mark[v]; 76 for(int i = 0; i < m; i++){ 77 if(!next[u][i] || !next[v][i]) next[u][i] += next[v][i]; 78 else Unit(next[u][i], next[v][i]); 79 } 80 } 81 }ac; 82 char str[N]; 83 set<ULL> st; 84 ULL v = 0; 85 int main(){ 86 int n, m, L = 0, len, k; 87 scanf("%d", &n); 88 for(int cas = 1; cas <= n; cas++){ 89 L = 0; 90 ac.init(); 91 st.clear(); 92 scanf("%d", &m); 93 printf("Case #%d: ", cas); 94 while(m--){ 95 scanf("%s", str); 96 len = strlen(str+1); 97 k = L % len; 98 reverse(str+1, str+1+k); 99 reverse(str+1+k, str+1+len); 100 reverse(str+1, str+1+len); 101 if(str[0] == '+'){ 102 v = 1; 103 for(int i = 1; str[i]; i++){ 104 v = v * 3 + (str[i]-'0'); 105 } 106 if(st.count(v)) continue; 107 else { 108 st.insert(v); 109 ac.Add(str+1,'0'); 110 } 111 } 112 else { 113 L = ac.Query(str+1, '0'); 114 printf("%d ", L); 115 } 116 } 117 } 118 return 0; 119 }