zoukankan      html  css  js  c++  java
  • POJ-3261-Milk Patterns(后缀数组)

    题意:

    给定一个字符串,求至少出现k 次的最长重复子串,这k 个子串可以重叠。

    分析:

    先二分答案,然后将后缀分成若干组。

    不同的是,这里要判断的是有没有一个组的后缀个数不小于k。

    如果有,那么存在k 个相同的子串满足条件,否则不存在。这个做法的时间复杂度为O(nlogn)。

    // File Name: 3261.cpp
    // Author: Zlbing
    // Created Time: 2013年09月04日 星期三 21时21分51秒
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    //rank从0开始
    //sa从1开始,因为最后一个字符(最小的)排在第0位
    //height从2开始,因为表示的是sa[i-1]和sa[i]
    const int MAXN=1e6+100;
    int rank[MAXN],sa[MAXN],X[MAXN],Y[MAXN],height[MAXN],s[MAXN];
    int buc[MAXN];
    void calheight(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] ; s[i+k] == s[j+k] ; k++);
    }
    bool cmp(int *r,int a,int b,int l) {
        return (r[a] == r[b] && r[a+l] == r[b+l]);
    }
    void suffix(int n,int m = 128) {
        int i , l , p , *x = X , *y = Y;
        for(i = 0 ; i < m ; i ++) buc[i] = 0;
        for(i = 0 ; i < n ; i ++) buc[ x[i] = s[i]  ] ++;
        for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
        for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[i] ]] = i;
        for(l = 1,p = 1 ; p < n ; m = p , l *= 2) {
            p = 0;
            for(i = n-l ; i < n ; i ++) y[p++] = i;
            for(i = 0 ; i < n ; i ++) if(sa[i] >= l) y[p++] = sa[i] - l;
            for(i = 0 ; i < m ; i ++) buc[i] = 0;
            for(i = 0 ; i < n ; i ++) buc[ x[y[i]] ] ++;
            for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
            for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[y[i]] ] ] = y[i];
            for(swap(x,y) , x[sa[0]] = 0 , i = 1 , p = 1 ; i < n ; i ++)
                x[ sa[i] ] = cmp(y,sa[i-1],sa[i],l) ? p-1 : p++;
        }
        calheight(n-1);//后缀数组关键是求出height,所以求sa的时候顺便把rank和height求出来
    }
    int n,k;
    bool judge(int x)
    {
        int cnt=1;
        for(int i=2;i<=n;i++)
        {
            if(height[i]>=x)
                cnt++;
            else cnt=1;
            if(cnt>=k)
                return true;
        }
        return false;
    }
    int main() {
        while(~scanf("%d%d",&n,&k))
        {
            REP(i,0,n-1)
                scanf("%d",&s[i]);
            REP(i,0,n-1)s[i]++;
            s[n]=0;
            suffix(n+1,1000002);
            int l=0,r=n,mid;
            int ans=-1;
            while(l<=r)
            {
                mid=l+(r-l+1)/2;
                if(judge(mid))
                {
                    ans=max(mid,ans);
                    l=mid+1;
                }
                else r=mid-1;
            }
            printf("%d
    ",ans);
        }
    
        return 0;
    }
  • 相关阅读:
    iOS 解决导航栏左右 BarButtonItem偏移位置的问题
    iOS UIButton 图片文字上下垂直布局 解决方案
    Android开发实战(十八):Android Studio 优秀插件:GsonFormat
    Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow
    AsyncTask.cancel()的结束问题
    Android项目实战(十五):自定义不可滑动的ListView和GridView
    RecyclerView解析--onViewDetachedFromWindow()/onViewAttachedToWindow()
    RecyclerView添加头部和底部视图的实现
    浅谈TabLayout(ViewPager+Tab联动)
    Android项目实战(十四):TextView显示html样式的文字
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3304516.html
Copyright © 2011-2022 走看看