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


    传送门

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

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

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

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

    把所有相邻的htht大于midmid化作一组

    取其中的最大最小值的差

    如果存在一组内的差大于midmid,返回TrueTrue,反之FalseFalse

    代码:

    #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=read();
        }
    }
    
  • 相关阅读:
    二叉树相关题目
    二叉树的遍历
    mysql获取某个表中除了某个字段名外的所有字段名
    设计模式之原型模式
    设计模式之工厂方法模式
    设计模式之代理模式
    设计模式之装饰模式
    设计模式之策略模式
    设计模式之简单工厂模式
    Redis的使用及参考代码
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366375.html
Copyright © 2020-2023  润新知