https://www.luogu.org/problemnew/show/P5287
题解
可持久化\(KMP\)。
那个退回操作我们可以把它看做在操作树上\(dfs\),所以我们可以先把这个树弄出来。
对于连续一段串的匹配问题。
我们可以搞个\(KMP\)自动机,输入当前节点编号也就是\(nxt\),输入下一段连续的字符串,输出\(nxt\)跳完之后的值。
然后我们可以把这个字符串的\(fail\)树弄出来,然后把它搞成一个主席树,相当于是我们令\(ch[now][c][len]\)为这个自动机,第三维比较大,用线段树维护,然后\(dfs\)这颗操作树的时候顺便维护这个节点的\(nxt\),这个点的主席树从fail节点继承。
还要维护从这个点到\(fail\)树根的一条链上\(x\)字符的最长长度,还要在线段树上维护匹配时产生的贡献。
注意特判一些情况比如说开头结尾的字符时一样的。
代码
#include
#define mm make_pair
#define P pair
#define ls tr[cnt].l
#define rs tr[cnt].r
#define N 100009
using namespace std;
typedef long long ll;
const int M=10001;
vectorvec[N];
const int mod=998244353;
int tot,head[N],rt[N][26],mx[N][26],pos[N],tag,top,n,tott,len[N];
P rec[N];
ll ans[N];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct node{
int l,r,nxt;
ll sum,la;
}tr[N*30];
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline int newnode(int pre){
++tott;
tr[tott]=tr[pre];
return tott;
}
inline void pushdown(int cnt,int l1,int l2){
ls=newnode(ls);
MOD(tr[ls].sum=l1*tr[cnt].la%mod);
rs=newnode(rs);
MOD(tr[rs].sum=l2*tr[cnt].la%mod);
tr[ls].la=tr[rs].la=tr[cnt].la;
tr[cnt].la=0;
}
void query(int cnt,int l,int r,int R,ll &ans,int &nxt){
if(r>1;
if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
query(ls,l,mid,R,ans,nxt);
if(mid>1;
if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
upd(ls,l,mid,R,x,nxt);
if(mid::iterator it=vec[u].begin();it!=vec[u].end();++it){
int v=*it;
ans[v]=ans[u];
memcpy(mx[top+1],mx[nxt+1],sizeof(mx[top+1]));
memcpy(rt[top+1],rt[nxt+1],sizeof(rt[top+1]));
dfs(v);
}
--top;
}
int main(){
n=rd();
int opt,x;
for(int i=1;i<=n;++i){
opt=rd();x=rd();
if(opt==1){
char c;
cin>>c;
rec[++tot]=mm(c-'a',x);
pos[i]=tot;
vec[pos[i-1]].push_back(pos[i]);
}
else{
pos[i]=pos[x];
}
}
for(vector::iterator it=vec[0].begin();it!=vec[0].end();++it){
int v=*it;
tott=0;
memset(rt[1],0,sizeof(rt[1]));
memset(mx[1],0,sizeof(mx[1]));
dfs(v);
}
for(int i=1;i<=n;++i)printf("%d\n",ans[pos[i]]);
return 0;
}