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;
    }
    
    
  • 相关阅读:
    软件工程第一次实验——软件开发文档与工具的安装与使用
    软件工程第四次作业——ATM管理系统
    软件工程第三次作业——举例分析流程图与活动图的区别与联系
    软件工程第二次作业——小学四则运算题目生成程序
    mac终端进入mysql
    计算机网络
    类和对象(未完成)
    html_css
    Mac下使用C语言生成和使用动态链接库
    模运算
  • 原文地址:https://www.cnblogs.com/nianheng/p/10066779.html
Copyright © 2011-2022 走看看