hdu 4787 GRE Words Revenge 在线AC自动机

hdu 4787

GRE Words Revenge

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 2505    Accepted Submission(s): 614

Problem Description

  Now Coach Pang is preparing for the Graduate Record Examinations as George did in 2011. At each day, Coach Pang can:
  "+w": learn a word w
  "?p": read a paragraph p, and count the number of learnt words. Formally speaking, count the number of substrings of p which is a learnt words.
  Given the records of N days, help Coach Pang to find the count. For convenience, the characters occured in the words and paragraphs are only ‘0‘ and ‘1‘.

Input

  The first line of the input file contains an integer T, which denotes the number of test cases. T test cases follow.
  The first line of each test case contains an integer N (1 <= N <= 105), which is the number of days. Each of the following N lines contains either "+w" or "?p". Both p and w are 01-string in this problem.
  Note that the input file has been encrypted. For each string occured, let L be the result of last "?" operation. The string given to you has been shifted L times (the shifted version of string s1s2 ... sk is sks1s2 ... sk-1). You should decrypt the string to the original one before you process it. Note that L equals to 0 at the beginning of each test case.
  The test data guarantees that for each test case, total length of the words does not exceed 105 and total length of the paragraphs does not exceed 5 * 106.

Output

  For each test case, first output a line "Case #x:", where x is the case number (starting from 1).
  And for each "?" operation, output a line containing the result.

Sample Input

2
3
+01
+01
?01001
3
+01
?010
?011

Sample Output

Case #1:
2
Case #2:
1
0

Source

2013 Asia Chengdu Regional Contest

可持久化,也就是可以在线,边询问边插入模式串,如果暴力每次插入后重建ac自动机,那么复杂度就是O(N*N),的,可以想到用分块(dalao是这么叫的);建立一个大的自动机,一个小的自动机,小的自动机规模是sqrt(N),大的是N,每次插入时在小的buf 里添加字串,重构自动机,当buf的规模超过sqrt(N)时,合并到大的自动机里大的重建,复杂度为O(sqrt(N) * N);合并就是buf 与ac 的字典树一起跑,如果ac里没有buf 的结点,就新建,然后权值|=buf.val[],(有节点也要| =,因为原来的不一定是单词,但现在是了);

  1 //2017-07-15 19:28:18
  2 //2017-07-15 20:10:10
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdlib>
  6 #include<cstdio>
  7 #include<cmath>
  8 #include<map>
  9 #include"set"
 10 #include"queue"
 11 #include"vector"
 12 #include"iomanip"
 13 #include"cstring"
 14 #define inf 1<<29
 15 #define ll long long
 16 #define re register
 17 #define il inline
 18 #define rep(i,a,b) for(register int i=a;i<=b;++i)
 19 #define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 20 using namespace std;
 21 const int N=100010;
 22 char tmp[5000100],s[5000100];
 23 struct ACAutomation{
 24     int f[N],ch[N][2],lst[N],sz;
 25     int val[N];
 26     il void init() {
 27         sz=0;ch[0][0]=ch[0][1]=0;lst[0]=0;
 28         //val[0]=0;
 29     }
 30     il int newnode(){
 31         ++sz;
 32         ch[sz][0]=ch[sz][1]=f[sz]=lst[sz]=0;
 33         val[sz]=0;//
 34         return sz;
 35     }
 36     il bool search(char *s,int len) {
 37         re int t=0,c;
 38         for(re int i=0;i<len;++i){
 39             c=s[i]-‘0‘;
 40             if(!ch[t][c])
 41                 return 0;
 42             t=ch[t][c];
 43         }
 44         return val[t];
 45     }
 46     il void insert(char *s,int len){
 47         re int t=0,c;
 48         for(re int i=0;i<len;++i){
 49             c=s[i]-‘0‘;
 50             if(!ch[t][c])
 51                 ch[t][c]=newnode();
 52             t=ch[t][c];
 53         }
 54         val[t]=1;
 55     }
 56     il void build() {
 57         queue<int> q;
 58         for(re int i=0;i<2;++i){
 59             if(ch[0][i])
 60                 q.push(ch[0][i]),f[ch[0][i]]=0,lst[ch[0][i]]=0;
 61         }
 62         re int r,v,u;
 63         while(!q.empty()) {
 64             r=q.front();q.pop();
 65             for(re int c=0;c<2;++c) {
 66                 u=ch[r][c];
 67                 if(!u) continue;
 68                 q.push(u);
 69                 v=f[r];
 70                 while(v&&!ch[v][c]) v=f[v];
 71                 f[u]=ch[v][c];
 72                 lst[u] = val[f[u]] ? f[u] : lst[f[u]];
 73             }
 74         }
 75     }
 76     il int run(char *s,int len) {
 77         re int t=0,ans=0,c;
 78         for(re int i=0;i<len;++i) {
 79             c=s[i]-‘0‘;
 80             while(t&&!ch[t][c]) t=f[t];
 81             t=ch[t][c];
 82             for(re int p=t;p;p=lst[p])
 83                 ans+=val[p];
 84         }
 85         return ans;
 86     }
 87 };
 88 ACAutomation ac,buf;
 89
 90 inline int gi() {
 91     re int res=0,f=1;re char ch=getchar();
 92     while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘) ch=getchar();
 93     if(ch==‘-‘) f=-1,ch=getchar();
 94     while(ch>=‘0‘&&ch<=‘9‘) res=res*10+ch-‘0‘,ch=getchar();
 95     return res*f;
 96 }
 97 il void bfs() {
 98     queue<int> U,V;
 99     U.push(0),V.push(0);
100     re int u,v,r1,r2;
101     while(!U.empty()) {
102         u=U.front(),v=V.front();
103         U.pop(),V.pop();
104         for(re int c=0;c<2;++c)
105             if(buf.ch[u][c]) {
106                 r1=buf.ch[u][c],r2=ac.ch[v][c];
107                 if(!r2) {
108                     ac.ch[v][c]=ac.newnode();
109                 }
110                 r2=ac.ch[v][c];
111                 ac.val[r2]|=buf.val[r1];
112                 U.push(r1),V.push(r2);
113             }
114     }
115 }
116 il void go() {
117     bfs();
118     buf.init();
119     ac.build();
120 }
121 int main(){
122     file("Y");
123     re int cas=gi();
124     rep(tt,1,cas) {
125         printf("Case #%d:\n",tt);
126         ac.init();
127         buf.init();
128         re int n=gi();
129         re int l=0;
130         rep(qyp,1,n) {
131             scanf("%s",tmp);
132             re int len=strlen(tmp);
133             re int p=l%(len-1);
134             s[0]=tmp[0];
135             for(re int i=1;i<=p;i++) s[i+len-1-p]=tmp[i];
136             for(re int i=1;i<len-p;++i) s[i]=tmp[i+p];
137             if(s[0]==‘+‘) {
138                 if(buf.search(s+1,len-1)||ac.search(s+1,len-1)) continue;
139                 buf.insert(s+1,len-1);
140                 buf.build();
141                 if(buf.sz>333) go();
142             }
143             else {
144                 l=ac.run(s+1,len-1) + buf.run(s+1,len-1);
145                 printf("%d\n",l);
146             }
147         }
148     }
149     return 0;
150 }
时间: 2024-10-15 14:23:06

hdu 4787 GRE Words Revenge 在线AC自动机的相关文章

HDU 3341 Lost&#39;s revenge(AC自动机+状压DP)

Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 4548    Accepted Submission(s): 1274 Problem Description Lost and AekdyCoin are friends. They always play "number game"(A bor

[HDU 4787] GRE Words Revenge (AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4787 题目大意: 给你若干个单词,查询一篇文章里出现的单词数.. 就是被我水过去的...暴力重建AC自动机- -然后暴力查找.. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #include <map> 6 #include

●HDU 4787 GRE Words Revenge

题链: http://acm.hdu.edu.cn/showproblem.php?pid=4787 题解: AC自动机(强制在线构造) 题目大意: 有两种操作, 一种为:+S,表示增加模式串S, 另一种为:?S,表示查询S中有多少子串为已经给出的模式串. (同时由于输入根据上一次的答案加密 ,所以强制在线) (事先提一下,对于多次给出的相同模式串,是要去重的,至于怎么去重,就随便用trie树或者map+string就好了.) 进入正题: 难道真的要让AC自动机变得在线起来么? 其实还是用普通A

HDU4787 GRE Words Revenge(AC自动机 分块 合并)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4787 Description Now Coach Pang is preparing for the Graduate Record Examinations as George did in 2011. At each day, Coach Pang can: "+w": learn a word w "?p": read a paragraph p, an

hdu_4787_GRE Words Revenge(在线AC自动机)

题目链接:hdu_4787_GRE Words Revenge 题意: 总共有n个操作,2种操作.每行读入一个字符串. 1.如果字符串以+开头,此为单词(即模式串,不考虑重复) 2.如果字符串以?开头,此为文章(即文本串,查询在此之前的单词在文本串中出现的次数) 题解: 强制在线的AC自动机 贴个大牛的详细题解http://blog.csdn.net/no__stop/article/details/16823479 这样的带合并操作的AC自动机用第二种建树的方式比较方便 1 #include<

HDOJ 题目4787 GRE Words Revenge(在线ac自动机,离线也可做)

GRE Words Revenge Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total Submission(s): 1570    Accepted Submission(s): 352 Problem Description Now Coach Pang is preparing for the Graduate Record Examinations as

HDU3341 Lost&#39;s revenge(AC自动机+DP)

题目是给一个DNA重新排列使其包含最多的数论基因. 考虑到内存大概就只能这么表示状态: dp[i][A][C][G][T],表示包含各碱基个数为ACGT且当前后缀状态为自动机第i的结点的字符串最多的数论基因数 其中ACGT可以hash成一个整数(a*C*G*T+c*G*T+g*T+T),这样用二维数组就行了,而第二维最多也就11*11*11*11个. 接下来转移依然是我为人人型,我是丢进一个队列,用队列来更新状态的值. 这题果然挺卡常数的,只好手写队列,最后4500msAC,还是差点超时,代码也

HDU 3065 病毒侵袭持续中 AC自动机题解

其实本题比HDU的病毒侵袭1还简单,不过有一个陷阱卡到我了:就是搜索text的时候,当遇到的字母不是大写字母的时候,那么就要重新从根节点开始搜索,否则就会答案错误. 那么一点陷阱,居然没想到啊. 教训啊:看来对不太平常的地方,需要更加深入的思考,才能发现其中的陷阱,否则就WA了. #include <stdio.h> #include <string.h> #include <queue> using std::queue; const int MAX_N = 1001

【HDU3341】 Lost&#39;s revenge (AC自动机+状压DP)

Lost's revenge Time Limit: 5000MS Memory Limit: 65535KB 64bit IO Format: %I64d & %I64u Description Lost and AekdyCoin are friends. They always play "number game"(A boring game based on number theory) together. We all know that AekdyCoin is t