• bzoj1396 识别子串


    建SAM,只有right集大小为1的节点对答案有贡献,

    若其出现位置右端点为r,此节点可接受的最短串长为x,最长串长为y,

    则对(r-x,r]用x更新最小值,对r-k (y<k≤x)则用k更新最小值

    用两棵线段树维护答案,分别处理以上两种情况

    #include<cstdio>
    #include<cstring>
    const int N=200005;
    int nx[N][26],fa[N],l[N],r[N],t[N],q[N],ql=0,qr=0,d[N],ptr=1,pv=1,len=0;
    char s[100005];
    void ins(int w,int pos){
        int p=pv,np=++ptr;
        t[np]=1;
        r[np]=pos;
        l[np]=l[p]+1;
        while(p&&!nx[p][w])nx[p][w]=np,p=fa[p];
        if(!p)fa[np]=1;
        else{
            int q=nx[p][w];
            if(l[q]==l[p]+1)fa[np]=q;
            else{
                int nq=++ptr;
                memcpy(nx[nq],nx[q],sizeof(nx[0]));
                l[nq]=l[p]+1;
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                while(p&&nx[p][w]==q)nx[p][w]=nq,p=fa[p];
            }
        }
        pv=np;
    }
    void build(){
        for(int i=1;i<=ptr;i++)++d[fa[i]];
        for(int i=1;i<=ptr;i++)if(!d[i])q[qr++]=i;
        while(ql!=qr){
            int w=q[ql++];
            int u=fa[w];
            if(!u)continue;
            t[u]+=t[w];
            r[u]=r[w];
            if(!--d[u])q[qr++]=u;
        }
    }
    int mn[262144],mn2[262144];
    inline void mins(int&a,int b){if(a>b)a=b;}
    void setmin(int l,int r,int x,int*mn){
        for(l+=131073,r+=131075;l^r^1;l>>=1,r>>=1){
            if(~l&1)mins(mn[l^1],x);
            if(r&1)mins(mn[r^1],x);
        }
    }
    int ans[100005];
    int main(){
        memset(mn,63,sizeof(mn));
        memset(mn2,63,sizeof(mn2));
        scanf("%s",s);
        for(len=0;s[len];++len)ins(s[len]-'a',len+1);
        build();
        for(int i=2;i<=ptr;i++)if(t[i]==1){
            int ml=l[fa[i]];
            setmin(r[i]-ml+1,r[i],ml+1,mn);
            setmin(r[i]-l[i]+1,r[i]-ml,r[i]+1,mn2);
        }
        for(int i=1;i<131072;i++){
            int lc=i<<1,rc=lc^1;
            mins(mn[lc],mn[i]),mins(mn[rc],mn[i]);
            mins(mn2[lc],mn2[i]),mins(mn2[rc],mn2[i]);
        }
        for(int i=1;i<=len;i++){
            ans[i]=mn[i+131074];
            mins(ans[i],mn2[i+131074]-i);
        }
        for(int i=1;i<=len;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    JS判断鼠标移入元素的方向
    EJB开发第一个无状态会话bean、开发EJBclient
    Android摇一摇振动效果Demo
    吃饭与团队惬意
    Factorization Machines 学习笔记(三)回归和分类
    代理---视图间数据的传递:标签显示输入的内容【多个视图中】
    cocos2d-x v3.2 FlappyBird 各个类对象详细代码分析(7)
    金典 SQL笔记(4)
    用GDB调试多进程程序
    C程序设计的抽象思维-算法分析-大多数元素
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5493776.html
Copyright © 2020-2023  润新知