• 【bzoj2555】substring


    蒟蒻有生之年终于切掉了这道题……在陈丽杰的sam课件上就有这道题,但是zcysky太菜一直不敢做。

    其实现在做一下,发现这个题目并不是太难。

    所谓的出现次数就是这个字符串在SAM上跑完对应的right集合。要支持及时插入,也就是要动态的维护Parent树的形态。

    “动态”,“树”,我们很明显本能的会想到动态树。此处动态树肯定是LCT。

    回顾Parent tree的性质, 一个父亲节点所表示的所有子串的出现位置相同

    并且为其所有子节点的子串的出现位置的集合的并。

    这个性质就是解决这道题的关键。

    所以我们可以用link-cut-tree维护这一棵Parent tree。(因为要支持加边,同时必须在线)

    在插入一个字符时, 对其所对应的parent tree上到根的路径上的节点全部加1. 查询时直接输出一个点上的值即可。

    路径修改,单点查询,LCT的权能。

    当然这个LCT不是我们平时见到的那种LCT。原因:

    1. 这是一棵有向树。换而言之,这题不可能有换根操作。(SAM的Parent树的形态是相对固定的)
    2. 注意link和cut的时候要消除之前的影响,体现在标记上。
    3. 查询的时候如果没有转移边(trans)可走,证明这个子串就没有出现过。

    然后就是……练习码力的时候了。

    其实最后写完也才一百多行

    你的幻想乡战略游戏,共价大爷游长沙不是也100多行吗!

    #include<bits/stdc++.h>
    #define N 1200005
    #define inf 1000000007
    using namespace std;
    int mask;char s[3000005];
    int Q;
    string chars;
    void gets(int mask){
        scanf("%s",s);chars=s;
        for(int j=0;j<chars.length();j++){
            mask=(mask*131+j)%chars.length();
            char t=chars[j];
            chars[j]=chars[mask];
            chars[mask]=t;
        }
    }
    struct Link_Cut_Tree{
        int top,fa[N],c[N][2],val[N],tag[N],q[N];
        inline void add(int x,int y){if(x)tag[x]+=y,val[x]+=y;}
        inline void pushdown(int x){
            int l=c[x][0],r=c[x][1];
            if(tag[x]){
                add(l,tag[x]);add(r,tag[x]);
                tag[x]=0;
            }
        }
        inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
        inline void rotate(int x){
            int y=fa[x],z=fa[y],l,r;
            if(c[y][0]==x)l=0;else l=1;r=l^1;
            if(!isroot(y)){if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;}
            fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
            c[y][l]=c[x][r];c[x][r]=y;
        }
        inline void splay(int x){
            int top=1;q[top]=x;
            for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
            for(int i=top;i;i--)pushdown(q[i]);
            while(!isroot(x)){
                int y=fa[x],z=fa[y];
                if(!isroot(y)){
                    if((c[z][0]==y)^(c[y][0]==x))rotate(x);
                    else rotate(y);
                }rotate(x);
            }
        }
        void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t;}
        inline void link(int x,int y){fa[x]=y;access(y);splay(y);add(y,val[x]);}
        inline void cut(int x){
            access(x);splay(x);add(c[x][0],-val[x]);
            fa[c[x][0]]=0;c[x][0]=0;
        }    
    }T;
    struct Suffix_AutoMaton{
        int l[N],fa[N],ch[N][26];
        int cnt,last;
        Suffix_AutoMaton(){cnt=1;last=1;}
        void ins(int c){
            int p=last,np=++cnt;last=np;T.val[np]=1;l[np]=l[p]+1;
            for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
            if(!p)fa[np]=1,T.link(np,1);
            else{
                int q=ch[p][c];
                if(l[p]+1==l[q])fa[np]=q,T.link(np,q);
                else{
                    int nq=++cnt;l[nq]=l[p]+1;
                    memcpy(ch[nq],ch[q],sizeof(ch[q]));
                    fa[nq]=fa[q];T.link(nq,fa[q]);
                    fa[np]=fa[q]=nq;
                    T.cut(q);T.link(q,nq);T.link(np,nq);
                    for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
                }
            }
        }
        void build(){
            scanf("%s",s);int len=strlen(s);
            for(int i=0;i<len;i++)ins(s[i]-'A');
        }
        int query(){
            gets(mask);
            int p=1;int len=chars.length();
            for(int i=0;i<len;i++)if(!(p=ch[p][chars[i]-'A']))return 0;
            T.splay(p);
            return T.val[p];
        }
        void add(){
            gets(mask);int len=chars.length();
            for(int i=0;i<len;i++)ins(chars[i]-'A');
        }
    }sam;
    int main(){
        scanf("%d",&Q);sam.build();
        while(Q--){
            scanf("%s",s);
            if(*s=='A')sam.add();
            else{
                int ans=sam.query();
                printf("%d
    ",ans);
                mask^=ans;
            }
        }
        return 0;
    }
  • 相关阅读:
    android 添加特定IP走局域网
    EF CORE 使用排他锁 干货 方法 悲观锁 entity framework 悲观锁
    VS C# xamarin 开发android 调试正常 发布分发后运行闪退出错
    .NET CORE 1.1 迁移到.NET 2.0正式版
    C# .NET Winform等程序一运行就闪退 不同环境 换到其他电脑,例如XP之类的解决方法。
    Cnblogs自定义皮肤css样式-星空观测者
    在桌面程序上和Metro/Modern/Windows store app的交互(相互打开,配置读取)
    适配各种Windows分辨率,为DPI添加感知,当在高DPI时,禁用WINFORM缩放等。
    为WIN8 APP创建置顶desktop应用
    React-Native 系列视频失效补链及一些碎碎念
  • 原文地址:https://www.cnblogs.com/zcysky/p/6851553.html
Copyright © 2020-2023  润新知