zoukankan      html  css  js  c++  java
  • POJ3261 Milk Patterns

    可重叠的k次最长重复子串
    利用后缀数组计算S和height数组
    然后二分,进行分组~

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e6+14;
    int sa[maxn];
    int t1[maxn];
    int t2[maxn];
    int c[maxn];
    int rk[maxn];
    int height[maxn];
    void build_sa (int s[],int n,int m) {
        int i,j,p;
        int *x=t1,*y=t2;
        for (i=0;i<m;i++) c[i]=0;
        for (i=0;i<n;i++) c[x[i]=s[i]]++;
        for (i=1;i<m;i++) c[i]+=c[i-1];
        for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
        for (j=1;j<=n;j<<=1) {
            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++) c[i]=0;
            for (i=0;i<n;i++) c[x[y[i]]]++;
            for (i=1;i<m;i++) c[i]+=c[i-1];
            for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;
            x[sa[0]]=0;
            for (i=1;i<n;i++) 
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
            if (p>=n) break;
            m=p; 
        }
    }
    void getHeight (int s[],int n) {
        int i,j,k=0;
        for (i=0;i<=n;i++) rk[sa[i]]=i;
        for (i=0;i<n;i++) {
            if (k) k--;
            j=sa[rk[i]-1];
            while (s[i+k]==s[j+k]) k++;
            height[rk[i]]=k;
        }
    }
    bool check (int n,int k,int t) {
        int num=1;
        for (int i=2;i<=n;i++) {
            if (height[i]>=t) {
                num++;
                if (num>=k) return true;
            }
            else num=1;
        }
        return false;
    }
    int s[maxn];
    int main () {
        int n,k;
        while (scanf("%d%d",&n,&k)==2) {
            int Max=0;
            for (int i=0;i<n;i++) {
                scanf ("%d",&s[i]);
                Max=max(Max,s[i]);
            }
            s[n]=0;
            build_sa(s,n+1,Max+1);
            getHeight(s,n);
            int l=0,r=n;
            int ans=0;
            while (l<=r) {
                int mid=(l+r)>>1;
                if (check(n,k,mid)) {
                    ans=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            printf ("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Linux找回root密码
    关于Linux的随笔笔记
    需求征集系统进度03
    需求征集系统进度02
    需求征集系统进度01
    第六周总结
    阅读笔记03
    第一周总结
    第五周总结
    阅读笔记02
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12332637.html
Copyright © 2011-2022 走看看