【POJ1743】—Musical Theme(后缀数组)

传送门

大意:给你一个字符串,求长度超过4、出现2次以上的最长串的长度

首先取相邻的差作为字符串

对这个串建立后缀数组之后

我们二分枚举这个最长串的长度

把所有相邻的 h t ht 大于 m i d mid 化作一组

取其中的最大最小值的差

如果存在一组内的差大于 m i d mid ,返回 T r u e True ,反之 F a l s e False

代码:

#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
inline int read(){
    char ch=getchar();
    int res=0;
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
const int N=20005;
const int inf=100000000;
int n,m,rk[N],sa[N],a[N],p[N],sa2[N],cnt[N],ht[N];
inline void bucket_sort(){
    for(int i=1;i<=m;i++)cnt[i]=0;
    for(int i=1;i<=n;i++)++cnt[rk[sa2[i]]];
    for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i>0;i--)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void init(){
    for(int i=1;i<=n;i++)rk[i]=a[i],sa2[i]=i;
    bucket_sort();
    for(int i=1,pos=0;i<=n&&pos<n;i<<=1){
        pos=0;
        for(int j=n-i+1;j<=n;j++)sa2[++pos]=j;
        for(int j=1;j<=n;j++)if(sa[j]>i)sa2[++pos]=sa[j]-i;
        bucket_sort();
        swap(rk,sa2);
        rk[sa[1]]=1,pos=1;
        for(int j=2;j<=n;j++)rk[sa[j]]=((sa2[sa[j]]==sa2[sa[j-1]])&&(sa2[sa[j]+i]==sa2[sa[j-1]+i])?pos:++pos);
        m=pos;
    }
    for(int i=1;i<=n;i++)rk[sa[i]]=i;
    for(int i=1,k=0,j;i<=n;ht[rk[i++]]=k){
        for(k?k--:0,j=sa[rk[i]-1];a[i+k]==a[j+k];k++);
    }
}
inline bool check(int k){
    int minn=inf,maxn=-inf;
    for(int i=1;i<=n;i++){
        if(ht[i]<k){maxn=-inf,minn=inf;continue;}
        maxn=max(maxn,max(sa[i],sa[i-1])),minn=min(minn,min(sa[i],sa[i-1]));
        if(maxn-minn>k)return true;
    }
    return false;
}
int main(){
    n=read();
    while(n){
        for(int i=1;i<=n;i++)p[i]=read();
        --n,m=176;
        for(int i=1;i<=n;i++)a[i]=p[i+1]-p[i]+88;
        init();
        int l=4,r=n,ans=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))l=mid+1,ans=mid;
            else r=mid-1;
        }
        if(!ans)ans=-1;
        ans++;
        cout<<ans<<'\n';
        n=read();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/85345326
今日推荐