• POJ 1743 Musical Theme


    后缀数组。求不可重叠最长重复子串。

    二分答案+验证。每一次二分,将排序完序的后缀按顺序进行分组。每组内任意两个的最长公共前缀要>=二分值。如果有一组内存在两个后缀的SA值相差大于等于二分值,那么这个二分值可行。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    inline int read()
    {
        char c = getchar();  while(!isdigit(c)) c = getchar();
        int x = 0;
        while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
        return x;
    }
    
    const int maxn=20000+10;
    
    int wa[maxn],wb[maxn],wv[maxn],WS[maxn];
    int cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0; i<m; i++) WS[i]=0;
        for(i=0; i<n; i++) WS[x[i]=r[i]]++;
        for(i=1; i<m; i++) WS[i]+=WS[i-1];
        for(i=n-1; i>=0; i--) sa[--WS[x[i]]]=i;
        for(j=1,p=1; p<n; j*=2,m=p)
        {
            for(p=0,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<n; i++) wv[i]=x[y[i]];
            for(i=0; i<m; i++) WS[i]=0;
            for(i=0; i<n; i++) WS[wv[i]]++;
            for(i=1; i<m; i++) WS[i]+=WS[i-1];
            for(i=n-1; i>=0; i--) sa[--WS[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
        return;
    }
    
    int rank[maxn],height[maxn];
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1; i<=n; i++) rank[sa[i]]=i;
        for(i=0; i<n; height[rank[i++]]=k)
            for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
        return;
    }
    
    int n,a[maxn],SA[maxn];
    
    bool check(int x)
    {
        int Min=SA[0],Max=SA[0]; height[n+1]=0;
        for(int i=1;i<=n+1;i++)
        {
            if(height[i]>=x) { Min=min(Min,SA[i]), Max=max(Max,SA[i]); continue; }
            if(Max-Min>=x) return 1;
            Min=SA[i]; Max=SA[i];
        }
        return 0;
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            if(n==0) break;
            for(int i=0;i<n;i++) scanf("%d",&a[i]); n--;
            for(int i=0;i<n;i++) a[i]=a[i+1]-a[i]+100;
            a[n]=0; da(a,SA,n+1,200); calheight(a,SA,n);
            
            int L=4,R=n+1,ans=0;
            while(L<=R)
            {
                int mid=(L+R)/2;
                if(check(mid)) ans=mid,L=mid+1;
                else R=mid-1;
            }
            ans++; if(ans<=4) ans=0;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    PHP页面跳转的几种方法
    PHP网站并发测试
    04-上传文件
    01-转>linux命令
    01-CDN的好处
    05-socket.io使用
    04-soket.io使用2 -数据同步简单聊天室效果
    03-socket.io 2.3.0版本的使用-用户请求接口,实时推送给前端数据
    02-转>
    跨域-转>预解析OPTIONS请求
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5720679.html
Copyright © 2020-2023  润新知