题意
你有一个字符串S,一开始为空串,要求支持两种操作
在S后面加入字母C
删除S最后一个字母
问每次操作后S有多少个不同的子串
前言
因为这题,我还倒回去复习了好一会的SAM。。
因为太久没有用过,都忘了。。
题解
很明显,题目给你的是一个字典树
然后你就可以dfs下去,然后顺便建立SAM
然后在回溯的时候将SAM还原。。
就可以
O
(
n
)
O(n)
O(n)地解决这个问题了
upd:这样复杂度应该是有问题的。。。挖坑
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100005;
char ss[N];
int len;
int now,tot,last;
struct qq
{
int son[26];
int fa;
int c;//他自己是什么字符
}o[N];
void bt ()
{
now=0;tot=0;
for (int u=0;u<len;u++)
{
if (ss[u]=='-') now=o[now].fa;
else
{
int x=ss[u]-'a';
if (o[now].son[x]==0)
{
o[now].son[x]=++tot;
o[tot].c=x;
o[tot].fa=now;
}
now=o[now].son[x];
}
}
}
struct qt{int son[26],step,pre;}s[N<<2];
int lalal=0;//现在有多少个不同的串了
struct qy
{
int x,y,z;
int op;//什么类型
}sta[N<<2];//撤销操作
int num=0;//当前撤销到哪里
void ins (int x)//插入这个新的点
{
int p=last,np=++tot;
s[np].step=s[p].step+1;
while (p!=0&&s[p].son[x]==0)
{
/**/
num++;
sta[num].x=p;sta[num].y=x;sta[num].z=s[p].son[x];sta[num].op=0;
/**/
s[p].son[x]=np,p=s[p].pre;
}
if (p==0) s[np].pre=1;
else
{
int q=s[p].son[x];
if (s[p].step+1==s[q].step) s[np].pre=q;
else
{
int nq=++tot;
s[nq]=s[q];
s[nq].step=s[p].step+1;
/**/
num++;
sta[num].x=q;sta[num].y=s[q].pre;sta[num].op=1;
/**/
s[q].pre=s[np].pre=nq;
while (p!=0&&s[p].son[x]==q)
{
/**/
num++;
sta[num].x=p;sta[num].y=x;sta[num].z=s[p].son[x];sta[num].op=0;
/**/
s[p].son[x]=nq;
p=s[p].pre;
}
}
}
lalal=lalal+s[np].step-s[s[np].pre].step;
last=np;
}
int ans[N];//每个节点的答案
void dfs (int x)
{
int now=num,shen=lalal,ooo=last;
ins(o[x].c);
ans[x]=lalal;
for (int u=0;u<26;u++)
if (o[x].son[u]!=0)
dfs(o[x].son[u]);
for (int u=now+1;u<=num;u++)//撤销操作
{
int x=sta[u].x,y=sta[u].y,z=sta[u].z;
if (sta[u].op==0)//son的修改
s[x].son[y]=z;
if (sta[u].op==1)//pre的修改
s[x].pre=y;
}
lalal=shen;last=ooo;num=now;
}
void solve ()
{
tot=1;
for (int u=0;u<26;u++)
if (o[0].son[u]!=0)
{
s[1].step=0;s[1].pre=0;
for (int i=0;i<26;i++) s[1].son[i]=0;
last=1;lalal=0;
dfs(o[0].son[u]);
}
now=0;
for (int u=0;u<len;u++)
{
if (ss[u]=='-') now=o[now].fa;
else
{
int x=ss[u]-'a';
now=o[now].son[x];
}
printf("%d\n",ans[now]);
}
}
int main()
{
scanf("%s",ss);len=strlen(ss);
bt();
solve();
return 0;
}