链接:http://acm.hdu.edu.cn/showproblem.php?pid=4641
题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作;操作分为:在末尾插入一个字符ch和查询不同子串出现次数不小于K的数量;
思路1:SAM在线求解;
对于每次找到将一个字符x插入到SAM之后,我们知道pre[p]所含有的Tx的后缀字符串数目为step[pre[np]]个,那么只需要每次插入之后更新下这些字符串出现的次数cnt即可;
由于Right(fa)与Right(r)没有交集(max(fa) = min(r) - 1),所以需要一直递推到root,但是root不能计算,因为root并没有表示后缀,只是一个init状态;
还有一点就是在拷贝q的信息到nq中时,主要把cnt的信息也拷贝过去;
由于数据较弱。。当出现5e4长度均为a的字符串,2e5次插入操作;这个算法复杂度将达到O(T*n*Q);
(因为每插入一个字符,都需要更新5e4次父节点,这时上面的flag优化没什么卵用。。)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 #define maxn 100007 7 #define SIGMA_SIZE 26 8 9 struct SAM{ 10 int sz,tot,last,k; 11 int g[maxn<<1][SIGMA_SIZE],pre[maxn<<1],step[maxn<<1]; 12 int vs[maxn<<1],cnt[maxn<<1]; 13 14 void newNode(int s){ 15 step[++sz] = s; 16 pre[sz] = 0; 17 vs[sz] = cnt[sz] = 0; 18 memset(g[sz],0,sizeof(g[sz])); 19 } 20 21 void init(){ 22 tot = 0; 23 sz = 0; last = 1; 24 newNode(0); 25 } 26 27 int idx(char ch){return ch - 'a';} 28 29 void Insert(char ch){ 30 newNode(step[last]+1); 31 int v = idx(ch), p = last, np = sz; 32 33 while(p && !g[p][v]) 34 g[p][v] = np,p = pre[p]; //知道找到Right集合中包含x的边的祖宗节点 35 36 if(p){ 37 int q = g[p][v]; 38 if(step[q] == step[p] + 1) 39 pre[np] = q; 40 else{ 41 newNode(step[p]+1); 42 int nq = sz; //nq替换掉q节点 43 for(int i = 0;i < SIGMA_SIZE;i++) 44 g[nq][i] = g[q][i]; 45 46 cnt[nq] = cnt[q]; //** 47 pre[nq] = pre[q]; 48 pre[np] = pre[q] = nq; 49 50 while(p && g[p][v] == q) 51 g[p][v] = nq,p = pre[p]; 52 } 53 } 54 else pre[np] = 1; 55 for(int aux = np;aux != 1 && !vs[aux];aux = pre[aux]){ 56 if(++cnt[aux] >= k){ 57 tot += step[aux] - step[pre[aux]]; 58 vs[aux] = true; //该父节点的子串已经加到tot中 59 } 60 } 61 last = np; 62 } 63 }SA; 64 char str[maxn]; 65 int main() 66 { 67 int n,Q; 68 while(scanf("%d%d%d",&n,&Q,&SA.k) == 3){ 69 scanf("%s",str); 70 SA.init(); 71 int len = strlen(str); 72 for(int i = 0;i < len;i++){ 73 SA.Insert(str[i]); 74 } 75 int op; 76 char ch[2]; 77 while(Q--){ 78 scanf("%d",&op); 79 if(op & 1){ 80 scanf("%s",ch); 81 SA.Insert(ch[0]); 82 } 83 else printf("%d\n",SA.tot); 84 } 85 } 86 }