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

     

    【题目链接】

     

      http://poj.org/problem?id=3261

     

    【题意】

     

      至少出现k次的可重叠最长子串。

     

    【思路】

           二分长度+划分height,然后判断是否存在一组的数目不小于k即可。

           需要注意的是:用末尾添0的方法解决n==1时的RE问题,但是在can中需要忽略height[0]且考虑height[1..n]。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     5 using namespace std;
     6 
     7 const int maxn = 20000+10;
     8 const int maxm = 1000000+10;
     9 
    10 int s[maxn];
    11 int sa[maxn],c[maxm],t[maxn],t2[maxn];
    12 
    13 void build_sa(int m,int n) {
    14     int i,*x=t,*y=t2;
    15     for(i=0;i<m;i++) c[i]=0;
    16     for(i=0;i<n;i++) c[x[i]=s[i]]++;
    17     for(i=1;i<m;i++) c[i]+=c[i-1];
    18     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    19     
    20     for(int k=1;k<=n;k<<=1) {
    21         int p=0;
    22         for(i=n-k;i<n;i++) y[p++]=i;
    23         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
    24         
    25         for(i=0;i<m;i++) c[i]=0;
    26         for(i=0;i<n;i++) c[x[y[i]]]++;
    27         for(i=0;i<m;i++) c[i]+=c[i-1];
    28         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
    29         
    30         swap(x,y);
    31         p=1; x[sa[0]]=0;
    32         for(i=1;i<n;i++) 
    33             x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
    34         if(p>=n) break;
    35         m=p;
    36     }
    37 }
    38 int rank[maxn],height[maxn];
    39 void getHeight(int n) {
    40     int i,j,k=0;
    41     for(i=0;i<=n;i++) rank[sa[i]]=i;
    42     for(i=0;i<n;i++) {
    43         if(k) k--;
    44         j=sa[rank[i]-1];
    45         while(s[j+k]==s[i+k]) k++;
    46         height[rank[i]]=k;
    47     }
    48 }
    49 
    50 int n,k;
    51 
    52 bool can(int limit) {
    53     int cnt=1;                //忽略height[0] 截至height[n]
    54     for(int i=2;i<=n;i++) {    
    55         if(height[i]>=limit) {
    56             if(++cnt>=k) return true;
    57         }
    58         else cnt=1;
    59     }
    60     return false;
    61 }
    62 
    63 int main() {
    64     scanf("%d%d",&n,&k);
    65     int up=0;
    66     FOR(i,0,n-1) {
    67          scanf("%d",&s[i]);
    68          s[i]++;
    69          up=max(up,s[i]);
    70     }
    71     s[n]=0;
    72     build_sa(up+1,n);
    73     getHeight(n);
    74     int L=0,R=n;
    75     while(L<R) {
    76         int M=L+(R-L+1)/2;
    77         if(can(M)) L=M;
    78         else R=M-1;
    79     }
    80     printf("%d
    ",L);
    81     return 0;
    82 }
  • 相关阅读:
    管理ceph缓存池
    Ceph更换OSD磁盘
    crushmap磁盘智能分组
    Angular 初体验
    音视频开发-FFmpeg
    开源项目OEIP 游戏引擎与音视频多媒体(UE4/Unity3D)
    Yolov3代码分析与训练自己数据集
    整合Yolov3到UE4/Unity3D
    CUDA版Grabcut的实现
    CUDA加opencv复现导向滤波算法
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5002310.html
Copyright © 2011-2022 走看看