CF204E Little Elephant and Strings(同bzoj3277)

来源:互联网 发布:软件开发做账 编辑:程序博客网 时间:2024/05/16 14:52

原题,还写了好久orz。传送门

#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 200010inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int nn,kk,a[N],m=30,n=0,count[N],rank[N<<1],rank1[N],sa[N],tmp[N];int cnt[N],bel[N],tot=0,L[N],len[N],h[N],Log[N],st[N][20];char s[N>>1];inline int lcp(int x,int y){    x++;int t=Log[y-x+1];    return min(st[x][t],st[y-(1<<t)+1][t]);}bool jud(int x,int len){    int xl,xr;    if(h[x]<len) xl=x;    else{        int l=1,r=x-1;        while(l<=r){            int mid=l+r>>1;            if(lcp(mid,x)>=len) r=mid-1;else l=mid+1;        }xl=r+1;    }    if(h[x+1]<len) xr=x;    else{        int l=x+1,r=n;        while(l<=r){            int mid=l+r>>1;            if(lcp(x,mid)>=len) l=mid+1;else r=mid-1;        }xr=l-1;    }    return xl<=L[xr];}int main(){//  freopen("a.in","r",stdin);    nn=read();kk=read();    for(int i=1;i<=nn;++i){        scanf("%s",s+1);len[i]=strlen(s+1);        for(int j=1;j<=len[i];++j) a[++n]=s[j]-'a'+1,bel[n]=i;a[++n]=++m;    }Log[0]=-1;    for(int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;    for(int i=1;i<=n;++i) count[a[i]]=1;    for(int i=1;i<=m;++i) count[i]+=count[i-1];    for(int i=n;i>=1;--i) rank[i]=count[a[i]];    int k=0;    for(int p=1;k!=n;p<<=1,m=k){        for(int i=1;i<=m;++i) count[i]=0;        for(int i=1;i<=n;++i) count[rank[i+p]]++;        for(int i=1;i<=m;++i) count[i]+=count[i-1];        for(int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;        for(int i=1;i<=m;++i) count[i]=0;        for(int i=1;i<=n;++i) count[rank[tmp[i]]]++;        for(int i=1;i<=m;++i) count[i]+=count[i-1];        for(int i=n;i>=1;--i) sa[count[rank[tmp[i]]]--]=tmp[i];        memcpy(rank1,rank,sizeof(rank1));        rank[sa[1]]=k=1;        for(int i=2;i<=n;++i){            if(rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+p]!=rank1[sa[i-1]+p]) ++k;            rank[sa[i]]=k;        }     }k=0;    for(int i=1;i<=n;++i){        if(rank[i]==1){h[1]=0;continue;}        if(i==1||h[rank[i-1]]<=1) k=0;        if(k) --k;        while(a[i+k]==a[sa[rank[i]-1]+k]) ++k;        h[rank[i]]=k;    }    for(int i=1;i<=n;++i) st[i][0]=h[i];    for(int i=1;i<=Log[n];++i)        for(int j=1;j<=n;++j)            if(j+(1<<i-1)<=n) st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);     //预处理L数组,表示L[i]~i满足有k个及以上个不同串且L[i]最大    for(int i=1,p=1;i<=n;++i){        if(!bel[sa[i]]) break;        if(++cnt[bel[sa[i]]]==1) ++tot;        while(tot>kk||tot==kk&&cnt[bel[sa[p]]]>1){            if(--cnt[bel[sa[p]]]==0) tot--;++p;        }if(tot>=kk) L[i]=p;else L[i]=-1;    }    for(int i=1,sta=1;i<=nn;++i,++sta){        int ed=sta+len[i]-1;ll ans=0;k=0;        for(int j=sta;j<=ed;++j){            if(k) --k;            while(j+k+1-1<=ed&&jud(rank[j],k+1)) ++k;            ans+=k;        }printf("%I64d",ans);if(i!=nn) putchar(' ');sta=ed+1;    }    return 0;}
原创粉丝点击