GRE Words Revenge AC自动机 二进制分组

GRE Words Revenge

题意和思路都和上一篇差不多。

有一个区别就是需要移动字符串。关于这个字符串,可以用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 }
View Code
原文地址:https://www.cnblogs.com/MingSD/p/9064571.html