• poj3261 Milk Patterns 后缀数组求可重叠的k次最长重复子串


    题目链接:http://poj.org/problem?id=3261

    思路:

    后缀数组的很好的一道入门题目

    先利用模板求出sa数组和height数组

    然后二分答案(即对于可能出现的重复长度进行二分) ,二分的时候,对 height进行分组,看是否存在一组height值使得其重复的次数大于等于k

    代码如下:

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 #define maxn 20010
     7 int wa[maxn],wb[maxn],wv[maxn],wq[maxn];
     8 int rank[maxn],sa[maxn];
     9 int r[maxn];
    10 int height[maxn];
    11 int s[maxn];
    12 int n,k;
    13 int cmp(int *r,int a,int b,int l)
    14 {
    15     return r[a]==r[b]&&r[a+l]==r[b+l];
    16 }
    17 void da(int *r,int *sa,int n,int m)
    18 {
    19     int i,j,p,*x=wa,*y=wb,*t;
    20     for(i=0;i<m;i++) wq[i]=0;
    21     for(i=0;i<n;i++) wq[x[i]=r[i]]++;
    22     for(i=1;i<m;i++) wq[i]+=wq[i-1];
    23     for(i=n-1;i>=0;i--) sa[--wq[x[i]]]=i;
    24 
    25     for(j=1,p=1;p<n;j*=2,m=p)
    26     {
    27        for(p=0,i=n-j;i<n;i++) y[p++]=i;
    28        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    29        for(i=0;i<n;i++) wv[i]=x[y[i]];
    30        for(i=0;i<m;i++) wq[i]=0;
    31        for(i=0;i<n;i++) wq[wv[i]]++;
    32        for(i=1;i<m;i++) wq[i]+=wq[i-1];
    33        for(i=n-1;i>=0;i--) sa[--wq[wv[i]]]=y[i];
    34        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
    35           x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    36    } 
    37    return ;
    38 } 
    39 void callheight(int *r,int n)
    40 {
    41      int i,j,k=0;
    42      for(i=1;i<=n;i++) rank[sa[i]]=i;
    43      for(i=0;i<n;i++)
    44         {
    45            if(k) k--;
    46            j=sa[rank[i]-1];
    47            while(r[i+k]==r[j+k]) k++;
    48            height[rank[i]]=k;
    49         }
    50 }
    51 bool check(int n,int mid)
    52 {
    53         int num=1;
    54      for(int i=2;i<=n;i++)
    55      {
    56         if(height[i]>=mid) 
    57         {
    58                 num++;
    59                 if(num>=k) 
    60                 return 1; 
    61         }
    62         else num=1;
    63      }
    64      return 0;
    65 }
    66 int main()
    67 {
    68         while(scanf("%d%d",&n,&k)!=EOF)
    69         {
    70                 int Maxx=0;
    71              for(int i=0;i<n;i++)
    72                  {
    73                          scanf("%d",&s[i]);
    74                          Maxx=max(Maxx,s[i]);
    75                  }
    76 
    77                  s[n]=0;
    78                  da(s,sa,n+1,Maxx+1);
    79                  callheight(s,n);
    80 
    81              int low=1,high=n-1;
    82              int ans=0;
    83              while(low<=high)
    84              {
    85                int mid=(low+high)/2;
    86                if(check(n,mid))
    87                {
    88                        ans=mid;
    89                        low=mid+1;
    90                }
    91                else high=mid-1;
    92              }
    93 
    94                 cout<<ans<<endl;
    95 
    96         }
    97         return 0;
    98 
    99 }
    View Code
  • 相关阅读:
    用C语言代码实现n进制数转换为十进制数
    RAID简介
    很久没更新自己的博客园的博客了
    微软之于程序员==铁饭碗破了
    sql编译执行过程
    sql server性能终结者锁
    sysprocesses
    SQL SERVER 2008的几个新东西:插入,删除,修改一起来(适合数据的同步)merger
    http Status Code Definitions
    sql server talbe valued parameters (tvp)
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/poj3261.html
Copyright © 2020-2023  润新知