zoukankan      html  css  js  c++  java
  • 后缀数组练习2:可重叠的k次最长重复子串

    其实和上一题是差不多的,只是在二分check的时候有一些小小的改动

    1468: 后缀数组2:可重叠的k次最长重复子串

    poj3261

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 113  解决: 48
    [提交] [状态] [讨论版] [命题人:admin]

    题目描述

    【问题描述】

    农夫John发现他的奶牛产奶的质量一直在变动。经过细致的调查,他发现:虽然他不能预见明天 产奶的质量,但连续的若干天的质量有很多重叠。我们称之为一个“模式”。 John的牛奶按质量可以被赋予一个0到1000000之间的数。并且John记录了N(1<=N<=20000)天的 牛奶质量值。他想知道最长的出现了至少K(2<=K<=N)次的模式的长度。 比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次。当K=2时,这个长度为4。(可重叠的k次最长重复子串)

    【输入格式】

    * Line 1: 两个整数 N,K。

    * Lines 2..N+1: 每行一个整数表示当天的质量值。

    (多组数据)

    【输出格式】

    * Line 1: 一个整数:N天中最长的出现了至少K次的模式的长度

    【样例】
    输入:

    8 2

    1

    2

    3

    2

    3

    2

    3

    1
    输出:

    做法是是和上一题:不可重叠的最长重复子串是差不多的,就是要判断后缀分成若干组,然后判断有没有一个组后缀个数是不小于k的,存在就满足,不存在就不满足
    代码实现,没什么注释,所以我就只放一个版本
     1 /*后将后缀分成若干组。 不同的是,这里要判断的是有没有一个组的后缀个数不小于 k。
     2 如果有,那么存在k 个相同的子串满足条件,否则不存在*/
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 #include<cmath>
     8 #include<iostream>
     9 using namespace std;
    10 int sa[1000010],Rank[1000010],rsort[1000010];
    11 int a[1000010],cnt[1000010],pos[100010],height[1000010];
    12 bool cmp(int x,int y,int k){return cnt[x]==cnt[y] && cnt[x+k]==cnt[y+k];}
    13 void get_sa(int n,int m) 
    14 {
    15     int k=1,p=0,len;
    16     for(int i=1;i<=n;i++) Rank[i]=a[i];
    17     memset(rsort,0,sizeof(rsort));
    18     for(int i=1;i<=n;i++) rsort[Rank[i]]++;
    19     for(int i=1;i<=m;i++) rsort[i]+=rsort[i-1];
    20     for(int i=n;i>=1;i--) sa[rsort[Rank[i]]--]=i;
    21     for(int k=1;k<n;k<<=1)
    22     {
    23         len=0;
    24         for(int i=n-k+1;i<=n;i++) pos[++len]=i;
    25         for(int i=1;i<=n;i++) if(sa[i]>k) pos[++len]=sa[i]-k;
    26         for(int i=1;i<=n;i++) cnt[i]=Rank[pos[i]];
    27         memset(rsort,0,sizeof(rsort));
    28         for(int i=1;i<=n;i++) rsort[cnt[i]]++;
    29         for(int i=1;i<=m;i++) rsort[i]+=rsort[i-1];
    30         for(int i=n;i>=1;i--) sa[rsort[cnt[i]]--]=pos[i];
    31         for(int i=1;i<=n;i++) cnt[i]=Rank[i];
    32         p=1; Rank[sa[1]]=1;
    33         for(int i=2;i<=n;i++)
    34         {
    35             if(!cmp(sa[i],sa[i-1],k)) p++;
    36             Rank[sa[i]]=p;
    37         }
    38         if(p==n) break; m=p;
    39     }
    40     a[0]=0; sa[0]=0;
    41 }
    42 void get_he(int n)
    43 {
    44     int j,k=0;
    45     for(int i=1;i<=n;i++)
    46     {
    47         j=sa[Rank[i]-1];
    48         if(k) k--;
    49         while(a[j+k]==a[i+k]) k++;
    50         height[Rank[i]]=k;
    51     }
    52 }
    53 bool check(int mid,int n,int k)
    54 {
    55     int sum=1;
    56     for(int i=2;i<=n;i++)
    57     {
    58         if(height[i]>=mid)/*满足条件*/
    59         {
    60             sum++;/*个数增加*/
    61             if(sum==k) return true;/*如果满足条件就直接返回*/
    62         }
    63         else sum=1;/*否则重新找*/
    64     }
    65     return false;
    66 }
    67 int main() 
    68 {
    69     int n,k;
    70     while(scanf("%d%d",&n,&k)!=EOF)
    71     {
    72         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    73         get_sa(n,1000010); get_he(n);
    74         int l=0,r=n,ans=0;
    75         while(l<=r)
    76         {
    77             int mid=(l+r)/2;
    78             if(check(mid,n,k))
    79             {
    80                 ans=mid;
    81                 l=mid+1;
    82             }
    83             else r=mid-1;
    84         }
    85         printf("%d
    ",ans);
    86     }
    87     return 0;
    88 }
    Tristan Code
  • 相关阅读:
    QML vs WEB
    《TO C产品经理进阶》
    《TO B产品设计标准化》
    《多元思维模型》跨学科及其核心思维模型
    产品经理审美训练
    Aria2多线程轻量级批量下载利器
    正则表达式
    如何开发一个用户脚本系列教程
    Aria2自动下载
    助贷
  • 原文地址:https://www.cnblogs.com/Tristanjiang/p/11381437.html
Copyright © 2011-2022 走看看