zoukankan      html  css  js  c++  java
  • 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
    ",tmp);
            mask^=tmp;
        }
        }
        return 0;
    }

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

    +本文作者:luyouqi233。               +

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

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

  • 相关阅读:
    MVC与MVVM
    js正则删除字符串中的部分内容(支持变量和特殊符号)
    小程序之rpx适配方案
    表单元素内容禁用拼写检查
    vue组件实例的生命周期
    Windows下生成目录结构树命令
    DRF之解析器源码解析
    restful规范快速记忆
    python报错之OSError
    xlrd、xlwt
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8792946.html
Copyright © 2011-2022 走看看