zoukankan      html  css  js  c++  java
  • POJ 1743 后缀数组

    题意:一道论文题,给定一串数组,求最长的重复子串长度,其中这两个子串不重叠,这两个子串可以相差同一个数字。

    分析:后一个减前一个数字,那么对于上面说的,可以相差同一个数字就变成了相同数字。问题就变成了,求一个串里面的最长不可重复的子串长度。

    但是不再是height数组里面的最大值了,二分答案,将height分成若干组(height数组是已经根据sa数组排好了的),记录每组里面的sa[] 最小值,sa[] 最大值,L + mid + 1<=R 即不重叠。

    最后大佬模板就是硬!

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1000000+5;
    
    int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
    int sa[maxn];
    int r[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 a[maxn];
    int n;
    
    const int INF = 0x3f3f3f3f;
    
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(scanf("%d",&n),n)
        {
            for(int i=0; i<n; i++)
                scanf("%d",&a[i]);
    
            for(int i=0; i<n-1; i++)
            {
                r[i] = a[i+1] - a[i]+100;
            }
    
            n--;
    
            da(r,sa,n+1,300);
            calheight(r,sa,n);
    
            int l = 1,r=n+1,mid;
            int L,R;
            while(l<=r)
            {
                mid = (l+r)/2;
                L = INF,R = -INF;
                bool flag = false;
                for(int i=1; i<=n; i++)
                {
                    if(height[i]>=mid)
                    {
                        L = min(L,sa[i]);
                        L = min(L,sa[i-1]);
                        R = max(R,sa[i]);
                        R = max(R,sa[i-1]);
                    }
                    else
                    {
                        if(L+mid+1<=R)
                        {
                            flag = true;
                            //break;
                        }
                        L = INF;
                        R = -INF;
                    }
                }
                if(L+mid+1<=R) flag = true;
                if(flag) l = mid + 1;
                else r = mid - 1;
            }
    
            if(l>=5)
                printf("%d
    ",l);
            else puts("0");
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    day01【MySQL数据库软件、SQL】
    【Junit单元测试、反射、注解】
    day13【Stream流、方法引用】
    day12【函数式接口】
    day11【网络编程】
    day10【缓冲流、转换流、序列化流】
    day09【字节流、字符流】
    day08【File类、递归】
    day07【线程池、Lambda表达式】
    day06 【线程、同步】
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7221484.html
Copyright © 2011-2022 走看看