BZOJ2555:SubString——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=2555

(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。

参考:https://www.cnblogs.com/zcysky/p/6851553.html

动态加字符串很容易想到后缀自动机。

如果暴力更新size(或者叫right?)以前是能过的,现在过不了。

但其实parent树本身就是树,用lct维护一下就可做了。

(树根和朝向一定所以不用rev当然用了也没人拦你。)

(很gg,更新lct需要打标记pushdown而不是upt,cut的节点也不要搞错了。)

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long ll;
const int N=1200005;
struct tree{
    int a[26],fa,l;
}ti[N];
char s[3000005],ch[300];
int last,cnt;
int a[N],w[N],size[N],tag[N];
int n,m,r,fa[N],tr[N][2],q[N];
inline void add(int x,int y){if(x)tag[x]+=y,size[x]+=y;}
inline bool get(int x){
    return tr[fa[x]][1]==x;
}
inline bool isroot(int x){
    if(!fa[x])return 1;
    return tr[fa[x]][0]!=x&&tr[fa[x]][1]!=x;
}
inline void push(int x){
    if(!tag[x])return;
    add(tr[x][0],tag[x]);
    add(tr[x][1],tag[x]);
    tag[x]=0;
}
inline void rotate(int x){
    int y=fa[x],z=fa[y],which=get(x);
    if(z&&!isroot(y))tr[z][tr[z][1]==y]=x;
    tr[y][which]=tr[x][which^1];fa[tr[y][which]]=y;  
    fa[y]=x;tr[x][which^1]=y;fa[x]=z;
}
inline void splay(int x){
    q[r=0]=x;
    for(int y=x;!isroot(y);y=fa[y])q[++r]=fa[y];
    for(int i=r;i>=0;i--)push(q[i]);
    while(!isroot(x)){
    if(!isroot(fa[x]))
        rotate((get(x)==get(fa[x])?fa[x]:x));
    rotate(x);
    }
}
inline void access(int x){
    for(int y=0;x;y=x,x=fa[x]){
    splay(x);tr[x][1]=y;
    if(y)fa[y]=x;
    }
}
inline void link(int x,int y){
    fa[x]=y;access(y);splay(y);add(y,size[x]);
}
inline void cut(int x){
    access(x);splay(x);add(tr[x][0],-size[x]);
    fa[tr[x][0]]=0;tr[x][0]=0;
}
inline void insert(int c){
    int p=last,np=++cnt;
    last=np;ti[np].l=ti[p].l+1;size[np]=1;
    for(;p&&!ti[p].a[c];p=ti[p].fa)ti[p].a[c]=np;
    if(!p){
    ti[np].fa=1;
    link(np,1);
    }
    else{
    int q=ti[p].a[c];
    if(ti[p].l+1==ti[q].l){
        ti[np].fa=q;
        link(np,q);
    }
    else{
        int nq=++cnt;ti[nq].l=ti[p].l+1;
        memcpy(ti[nq].a,ti[q].a,sizeof(ti[q].a));
        cut(q);
        link(nq,ti[q].fa);link(q,nq);link(np,nq);
        ti[nq].fa=ti[q].fa;ti[q].fa=ti[np].fa=nq;
        for(;p&&ti[p].a[c]==q;p=ti[p].fa)ti[p].a[c]=nq;
    }
    }
}
inline int query(int len){
    int now=1;
    for(int i=0;i<len;i++){
    if(ti[now].a[s[i]-'A']){
        now=ti[now].a[s[i]-'A'];
    }else return 0;
    }
    access(now);splay(now);
    return size[now];
}
int main(){
    last=cnt=1;
    int q,mask=0,len,res;
    scanf("%d%s",&q,s);
    len=strlen(s);
    for(int i=0;i<len;i++)insert(s[i]-'A');
    while(q--){
    scanf("%s%s",ch,s);
    len=strlen(s);res=mask;
    for(int i=0;i<len;i++){
        res=(res*131+i)%len;
        swap(s[i],s[res]);
    }
    if(ch[0]=='A'){
        for(int i=0;i<len;i++)insert(s[i]-'A');
    }else{
        int tmp=query(len);
        printf("%d\n",tmp);
        mask^=tmp;
    }
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-04-11 08:03  luyouqi233  阅读(186)  评论(0编辑  收藏  举报