spoj 220. Relevant Phrases of Annihilation

来源:互联网 发布:怎么取消淘宝延迟收款 编辑:程序博客网 时间:2024/04/30 02:12

题目链接:http://www.spoj.pl/problems/PHRASES/

题目思路:二分答案,然后分组,看一组中是否包含所有字符串,且每个字符串出现两次及两次以上,然后距离差大于等于k。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<vector>#include<stack>#include<list>#include<iostream>#include<map>using namespace std;#define inf 0x3f3f3f3f#define M 110000int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}int rank[M],sa[M],height[M];int ta[M],tb[M],tv[M],ts[M],r[M],pos[M];bool cmp(int *y,int a,int b,int l){    return y[a]==y[b]&&y[a+l]==y[b+l];}void da(int n,int m){    int i,j,p,*x=ta,*y=tb;    for(i=0;i<m;i++) ts[i]=0;    for(i=0;i<n;i++) ts[x[i]=r[i]]++;    for(i=1;i<m;i++) ts[i]+=ts[i-1];    for(i=n-1;i>=0;i--) sa[--ts[x[i]]]=i;    for(j=1,p=1;p<n;j*=2,m=p)    {        p=0;        for(i=n-j;i<n;i++) y[p++]=i;        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;        for(i=0;i<m;i++) ts[i]=0;        for(i=0;i<n;i++) tv[i]=x[y[i]];        for(i=0;i<n;i++) ts[tv[i]]++;        for(i=1;i<m;i++) ts[i]+=ts[i-1];        for(i=n-1;i>=0;i--) sa[--ts[tv[i]]]=y[i];        swap(x,y);        x[sa[0]]=0;        p=1;        for(i=1;i<n;i++)        {            if(cmp(y,sa[i-1],sa[i],j)) x[sa[i]]=p-1;            else  x[sa[i]]=p++;        }    }}void calh(int n){    int i,k,tmp;    for(i=1;i<=n;i++) rank[sa[i]]=i;    k=0;    for(i=0;i<n;i++)    {        tmp=sa[rank[i]-1];        for(;r[i+k]==r[tmp+k];k++)        ;        height[rank[i]]=k;        k?--k:0;    }}int check(int tp,int n,int k){    int i,j,tmp,num=0,mi[12],mx[12];    for(i=0;i<tp;i++)    {        mi[i]=-1,mx[i]=-1;    }    tmp=pos[sa[1]];    mi[tmp]=mx[tmp]=sa[1];    for(i=2;i<=n;i++)    {        if(height[i]<k)        {            num=0;            for(j=0;j<tp;j++)            {                if(mi[j]!=-1&&mx[j]-mi[j]>=k) num++;                mi[j]=mx[j]=-1;            }            if(num==tp)                return 1;            tmp=pos[sa[i]];            mi[tmp]=mx[tmp]=sa[i];        }        else        {            tmp=pos[sa[i]];            if(mi[tmp]==-1)                mi[tmp]=mx[tmp]=sa[i];            else            {                mi[tmp]=min(mi[tmp],sa[i]);                mx[tmp]=max(mx[tmp],sa[i]);            }        }    }    num=0;    for(j=0;j<tp;j++)    {        if(mi[j]!=-1&&mx[j]-mi[j]>=k) num++;        mi[j]=mx[j]=-1;    }    if(num==tp)        return 1;    return 0;}void getans(int l,int r,int n,int tp){    int mid;    while(l<=r)    {        mid=(l+r)>>1;        if(check(tp,n,mid)) l=mid+1;        else r=mid-1;    }    printf("%d\n",r);}char s[M];int main(){    int t,i,j,n,len,mi,tp;    scanf("%d",&t);    while(t--)    {        scanf("%d",&tp);        n=0;        mi=inf;        for(i=0;i<tp;i++)        {            scanf("%s",s);            len=strlen(s);            mi=min(mi,len);            for(j=n;j<n+len;j++)            {                r[j]=s[j-n];pos[j]=i;            }            r[n+len]=129+i;            pos[n+len]=i;            n+=len+1;        }        n--;r[n]=0;        da(n+1,200);        calh(n);        getans(1,mi,n,tp);    }}


 

原创粉丝点击