zoukankan      html  css  js  c++  java
  • BZOJ-1396: 识别子串

    后缀自动机+线段树

    先建出$sam$,统计一遍每个点的$right$集合大小$siz$,对于$siz=1$的点$x$,他所代表的子串只会出现一次,设$y=fa[x](,则这个点代表的子串即为)(1...len[x]-len[y],len[x])(,对于子串)(len[x]-len[y],len[x])$的每一个点,这个子串都是他的识别子串,长度固定$len[y]+1$,而对于一个点$iin[1,len[x]-len[y]-1](,子串)(i,len[x])$一定是他的一个识别子串,长度$len[x]+1-i$。可以用两棵线段树分别存$len[y]+1$与$len[x]+1$,单点查询最小值得到答案

    #include<map>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+100;
    struct xdt{
        int poi[maxn<<2],lazy[maxn<<2];
        void updata(int x){
            poi[x]=min(poi[x<<1],poi[x<<1|1]);
        }
        void pushdown(int x){
            if(!lazy[x]) return;
            poi[x<<1]=min(poi[x<<1],lazy[x]);
            lazy[x<<1]=lazy[x<<1]?min(lazy[x<<1],lazy[x]):lazy[x];
            poi[x<<1|1]=min(poi[x<<1|1],lazy[x]);
            lazy[x<<1|1]=lazy[x<<1|1]?min(lazy[x<<1|1],lazy[x]):lazy[x];
            lazy[x]=0;
        }
        void build(int l,int r,int now){
            poi[now]=0x7fffffff;
            if(l==r) return;
            int mid=l+r>>1;
            build(l,mid,now<<1);
            build(mid+1,r,now<<1|1);
        }
        void revise(int lc,int rc,int l,int r,int now,int z){
            if(lc==l&&rc==r){
                poi[now]=min(poi[now],z);
                if(lazy[now]==0) lazy[now]=z;
                else lazy[now]=min(lazy[now],z);
                return;
            }
            pushdown(now);
            int mid=lc+rc>>1;
            if(l<=mid) revise(lc,mid,l,min(mid,r),now<<1,z);
            if(r>mid) revise(mid+1,rc,max(mid+1,l),r,now<<1|1,z);
            updata(now);
        }
        int query(int lc,int rc,int x,int now){
            if(lc==rc) return poi[now];
            pushdown(now);
            int mid=lc+rc>>1;
            if(x<=mid) return query(lc,mid,x,now<<1);
            else return query(mid+1,rc,x,now<<1|1);
        }
    }t1,t2;
    struct SAM{
        int son[maxn][26],len[maxn],siz[maxn],fa[maxn],tax[maxn],a[maxn];
        int tot,last,n;
        char s[maxn];
        void insert(int x){
            int p=last,np=++tot;
            len[np]=len[p]+1;
            siz[np]=1;
            while(~p&&!son[p][x])
                son[p][x]=np,p=fa[p];
            if(p==-1)
                fa[np]=0;
            else{
                int q=son[p][x];
                if(len[q]==len[p]+1)
                    fa[np]=q;
                else{
                    int nq=++tot;
                    memcpy(son[nq],son[q],sizeof(son[q]));
                    fa[nq]=fa[q];
                    len[nq]=len[p]+1;
                    fa[q]=fa[np]=nq;
                    while(~p&&son[p][x]==q)
                        son[p][x]=nq,p=fa[p];
                }
            }
            last=np;
        }
        void Qsort(){
            for(int i=0;i<=n;i++) tax[i]=0;
            for(int i=1;i<=tot;i++) tax[len[i]]++;
            for(int i=1;i<=n;i++) tax[i]+=tax[i-1];
            for(int i=1;i<=tot;i++) a[tax[len[i]]--]=i;
        }
        void ycl(){
            last=tot=0,fa[0]=-1;
            for(int i=1;i<=n;i++) insert(s[i]-'a');
            Qsort();
            for(int i=tot;i>=1;i--) siz[fa[a[i]]]+=siz[a[i]];
            t1.build(1,n,1),t2.build(1,n,1);
            for(int i=1;i<=tot;i++)
                if(siz[i]==1){
                    int l=len[i]-len[fa[i]],r=len[i];
                    t1.revise(1,n,l,r,1,r-l+1);
    //              printf("->%d
    ",t1.query(1,n,2,1));
                    if(l!=1) t2.revise(1,n,1,l-1,1,r+1);
                }
        }
        void query(){
    //              printf("->%d
    ",t1.query(1,n,2,1));
            for(int i=1;i<=n;i++)
                printf("%d
    ",min(t1.query(1,n,i,1),t2.query(1,n,i,1)-i));
        }
    }sam;
    int main(){
    //  freopen(".in","r",stdin);
        scanf("%s",sam.s+1),sam.n=strlen(sam.s+1);
        sam.ycl();
        sam.query();
        return 0;
    }
    
    
  • 相关阅读:
    数据库表结构变动发邮件脚本
    .net程序打包部署
    无法登陆GitHub解决方法
    netbeans 打包生成 jar
    第一次值班
    RHEL6 纯命令行文本界面下安装桌面
    C语言中格式化输出,四舍五入类型问题
    I'm up to my ears
    How to boot ubuntu in text mode instead of graphical(X) mode
    the IP routing table under linux@school
  • 原文地址:https://www.cnblogs.com/nianheng/p/10066779.html
Copyright © 2011-2022 走看看