• bzoj1396 识别子串


    题目描述

    题解:

    好神啊

    建出后缀自动机,然后处理每个点parent树子树中endpos的数量,若为1即可成为识别子串。

    对于每个点维护原串所在位置以及right的最小值mn。

    然后套上线段树维护区间最小值。

    基本就这样了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    char s[N];
    struct Point
    {
        int len,pre,trs[28],pla;
    }p[2*N];
    int hed[2*N],cnt,n;
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int mn[2*N],siz[2*N];
    struct SAM
    {
        int tot,las;
        SAM(){tot=las=1;}
        void insert(int c)
        {
            int np,nq,lp,lq;
            np=++tot;
            siz[np] = 1;
            p[np].len = p[las].len + 1;
            p[np].pla = p[las].pla + 1;
            for(lp = las;lp&&!p[lp].trs[c];lp=p[lp].pre)
                p[lp].trs[c] = np;
            if(!lp)p[np].pre = 1;
            else
            {
                lq = p[lp].trs[c];
                if(p[lq].len == p[lp].len+1)p[np].pre = lq;
                else
                {
                    nq = ++tot;
                    p[nq] = p[lq];
                    p[nq].len = p[lp].len+1;
                    p[lq].pre = p[np].pre = nq;
                    while(p[lp].trs[c]==lq)
                    {
                        p[lp].trs[c] = nq;
                        lp = p[lp].pre;
                    }
                }
            }
            las = np;
        }
        void dfs(int u){for(int j=hed[u];j;j=e[j].nxt)dfs(e[j].to),siz[u]+=siz[e[j].to];}
        void build()
        {
            for(int i=2;i<=tot;i++)
            {
                mn[i] = p[p[i].pre].len+1;
                ae(p[i].pre,i);
            }
            dfs(1);
        }
    }sam;
    int ans[N];
    struct segtree
    {
        int v[N<<2];
        void pushdown(int u)
        {
            v[u<<1]=min(v[u<<1],v[u]);
            v[u<<1|1]=min(v[u<<1|1],v[u]);
        }
        void build(int u,int l,int r)
        {
            v[u]=n;
            if(l==r)return ;
            int mid = (l+r)>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
        }
        void insert(int u,int l,int r,int ql,int qr,int d)
        {
            if(l==ql&&r==qr)
            {
                v[u] = min(v[u],d);
                return ;
            }
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)insert(u<<1,l,mid,ql,qr,d);
            else if(ql>mid)insert(u<<1|1,mid+1,r,ql,qr,d);
            else insert(u<<1,l,mid,ql,mid,d),insert(u<<1|1,mid+1,r,mid+1,qr,d);
        }
        void down(int u,int l,int r)
        {
            if(l==r)
            {
                ans[l]=v[u];
                return ;
            }
            pushdown(u);
            int mid = (l+r)>>1;
            down(u<<1,l,mid);
            down(u<<1|1,mid+1,r);
        }
    }tr;
    int main()
    {
        scanf("%s",s+1);
        n = strlen(s+1);
        for(int i=1;i<=n;i++)
            sam.insert(s[i]-'a'+1);
        sam.build();
        tr.build(1,1,n);
        for(int i=1;i<=sam.tot;i++)
        {
            if(siz[i]==1)
            {
                tr.insert(1,1,n,p[i].pla-mn[i]+1,p[i].pla,mn[i]);
            }
        }
        tr.down(1,1,n);
        for(int i=2;i<=n;i++)ans[i] = min(ans[i],ans[i-1]+1);
        for(int i=n-1;i>=1;i--)ans[i] = min(ans[i],ans[i+1]+1);
        for(int i=1;i<=n;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    matplotlib 柱状图
    JavaScript 箭头函数
    JavaScript map reduce
    JavaScript sort函数
    JavaScript var、let、const
    javaScript 迭代器
    javaScript map和set
    批处理学习(-)之文件夹和文件的移动
    让 Lua 访问数据库
    lua 模块化推荐方法
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10104201.html
Copyright © 2020-2023  润新知