bzoj2865: 字符串识别(后缀自动机 + 线段树)

https://www.lydsy.com/JudgeOnline/problem.php?id=2865

 

同上一篇博客

就是卡卡空间,数组改成map

 

#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
#define N 500001
 
using namespace std;
 
char s[N];
 
map<int,int>ch[N<<1];
int tot=1;

int fa[N<<1],len[N<<1];
int siz[N<<1]; 
int last=1,p,q,np,nq;
 
int leaf[N];
 
int v[N],sa[N<<1];
 
struct Segment
{
    int mx[N<<2];
    int tag[N<<2];
 
    void down(int k)
    {
        mx[k<<1]=min(mx[k<<1],tag[k]);
        mx[k<<1|1]=min(mx[k<<1|1],tag[k]);
        tag[k<<1]=min(tag[k<<1],tag[k]);
        tag[k<<1|1]=min(tag[k<<1|1],tag[k]);
        tag[k]=2e9;
    }
 
    void build(int k,int l,int r)
    {
        mx[k]=tag[k]=2e9;
        if(l==r) return;
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
 
    void change(int k,int l,int r,int opl,int opr,int w)
    {
        if(l>=opl && r<=opr)
        {
            mx[k]=min(mx[k],w);
            tag[k]=min(tag[k],w);
            return;
        }
        int mid=l+r>>1;
        if(tag[k]!=2e9) down(k);
        if(opl<=mid) change(k<<1,l,mid,opl,opr,w);
        if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,w);
        mx[k]=min(mx[k<<1],mx[k<<1|1]);
    }
 
    int query(int k,int l,int r,int x)
    {
        if(l==r) return mx[k];
        int mid=l+r>>1;
        if(tag[k]!=2e9) down(k);
        if(x<=mid) return query(k<<1,l,mid,x);
        return query(k<<1|1,mid+1,r,x);
    }
};
 
Segment tr1,tr2;
 
void extend(int c)
{
    len[np=++tot]=len[last]+1;
    siz[tot]=1;
    for(p=last;p && ch[p].find(c)==ch[p].end();p=fa[p]) ch[p][c]=np;
    if(!p) fa[np]=1;
    else
    {
        q=ch[p][c];
        if(len[q]==len[p]+1) fa[np]=q;
        else
        {
            nq=++tot;
            fa[nq]=fa[q];
            ch[nq]=ch[q];
            fa[q]=fa[np]=nq;
            len[nq]=len[p]+1;
            for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
        }
    }
    last=np;
}
     
int main()
{
    scanf("%s",s+1);
    int n=strlen(s+1);
    for(int i=1;i<=n;++i) 
    {
        leaf[i]=tot+1;
        extend(s[i]-'a');
    }
    for(int i=1;i<=tot;++i) v[len[i]]++;
    for(int i=1;i<=n;++i) v[i]+=v[i-1];
    for(int i=1;i<=tot;++i) sa[v[len[i]]--]=i;
    int x;
    for(int i=tot;i;--i)
    {
        x=sa[i];
        siz[fa[x]]+=siz[x];
    }
    tr1.build(1,1,n);
    tr2.build(1,1,n);
    int l,r,end;
    for(int x=2;x<=tot;++x)
    if(siz[x]==1)
    {
        l=len[fa[x]];
        r=len[x];
        end=len[x];
        tr1.change(1,1,n,end-l,end,l+1);
        tr2.change(1,1,n,end-r+1,end-l,end+1);
    }
    int a,b;
    for(int i=1;i<=n;++i)
    {
        a=tr1.query(1,1,n,i);
        b=tr2.query(1,1,n,i)-i;
        printf("%d\n",min(a,b));
    }
    return 0;
}
posted @ 2018-05-03 17:12  TRTTG  阅读(530)  评论(0编辑  收藏  举报