BZOJ2555 SubString 【后缀自动机 + LCT】

题目

懒得写背景了，给你一个字符串init，要求你支持两个操作

(1):在当前字符串的后面插入一个字符串

(2):询问字符串s在当前字符串中出现了几次？(作为连续子串)



输入格式

第一行一个数Q表示操作个数

Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。



输入样例

2

A

QUERY B



输出样例

0


提示

40 % 的数据字符串最终长度 <= 20000，询问次数<= 1000，询问总长度<= 10000

100 % 的数据字符串最终长度 <= 600000，询问次数<= 10000,询问总长度<= 3000000

题解

【orz hzwer】

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define isr(u) (ch[fa[u]][1] == u)
#define isrt(u) (!fa[u] || (ch[fa[u]][0] != u && ch[fa[u]][1] != u))
#define ls ch[u][0]
#define rs ch[u][1]
using namespace std;
const int maxn = 1200005,maxm = 3000005,INF = 1000000000;
int fa[maxn],tag[maxn],val[maxn],ch[maxn][2];
int pre[maxn],son[maxn][26],step[maxn],cnt,last,n;
char s[maxm];
void add(int u,int v){if (u) val[u] += v,tag[u] += v;}
void pd(int u){
}
void push_down(int u){
if (!isrt(u)) push_down(fa[u]); pd(u);
}
void spin(int u){
int s = isr(u),f = fa[u];
fa[u] = fa[f]; if (!isrt(f)) ch[fa[f]][isr(f)] = u;
ch[f][s] = ch[u][s ^ 1]; if (ch[u][s ^ 1]) fa[ch[u][s ^ 1]] = f;
fa[f] = u; ch[u][s ^ 1] = f;
}
void splay(int u){
for (push_down(u); !isrt(u); spin(u))
if (!isrt(fa[u])) spin((isr(u) ^ isr(fa[u])) ? u : fa[u]);
}
void Access(int u){
for (int v = 0; u; u = fa[v = u]) splay(u),rs = v;
}
void Cut(int u){
fa[ls] = 0; ls = 0;
}
fa[u] = f; Access(f); splay(f); add(f,val[u]);
}
void ins(int x){
int p = last,np = ++cnt;
last = np; val[np] = 1; step[np] = step[p] + 1;
while (p && !son[p][x]) son[p][x] = np,p = pre[p];
else {
int q = son[p][x];
if (step[q] == step[p] + 1) pre[np] = q,Link(np,q);
else {
int nq = ++cnt; step[nq] = step[p] + 1;
memcpy(son[nq],son[q],sizeof(son[q]));
while (son[p][x] == q) son[p][x] = nq,p = pre[p];
}
}
}
n = strlen(s);
for (int j = 0; j < n; j++){
}
}
int solve(){
for (int i = 0; i < n; i++)
if (!(u = son[u][s[i] - 'A'])) return 0;
splay(u);
return val[u];
}
int main(){
int Q,ans; scanf("%d",&Q);
scanf("%s",s);
n = strlen(s); cnt = last = 1;
for (int i = 0; i < n; i++) ins(s[i] - 'A');
while (Q--){
scanf("%s",s);
if (s[0] == 'A'){