• POJ 3261 Milk Patterns(后缀数组+单调队列)


    题意

    找出出现k次的可重叠的最长子串的长度

    题解

    用后缀数组。

    然后求出heigth数组。

    跑单调队列就行了。找出每k个数中最小的数的最大值。就是个滑动窗口啊

    (不知道为什么有人写二分,其实写啥都差不多快,可能是因为二分是一个常见的模型吧)

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1000100;
     8 int n,m,x[N],sa[N],c[N],k,height[N],rk[N],y[N],ans,q[N],head,tail,s[N];
     9 void get_sa(){
    10     for(int i=1;i<=n;i++)c[x[i]=s[i]]++;
    11     for(int i=1;i<=m;i++)c[i]+=c[i-1];
    12     for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
    13     for(int k=1;k<=n;k<<=1){
    14         int num=0;
    15         for(int i=n-k+1;i<=n;i++)y[++num]=i;
    16         for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
    17         for(int i=1;i<=m;i++)c[i]=0;
    18         for(int i=1;i<=n;i++)c[x[i]]++;
    19         for(int i=1;i<=m;i++)c[i]+=c[i-1];
    20         for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;
    21         for(int i=1;i<=n;i++){
    22             swap(x[i],y[i]);
    23         }
    24         x[sa[1]]=1;num=1;
    25         for(int i=2;i<=n;i++){
    26             x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
    27         } 
    28         if(n==num)break;
    29         m=num;
    30     }
    31 }
    32 void get_height(){
    33     for(int i=1;i<=n;i++)rk[sa[i]]=i;
    34     int k=0;
    35     for(int i=1;i<=n;i++){
    36         if(rk[i]==1)continue;
    37         if(k)k--;
    38         int j=sa[rk[i]-1];
    39         while(j+k<=n&&i+k<=n&&s[j+k]==s[i+k])k++;
    40         height[rk[i]]=k;
    41     }
    42 }
    43 int main(){
    44     scanf("%d%d",&n,&k);
    45     if(k==1){
    46         printf("%d",n);
    47         return 0;
    48     }
    49     m=1000005;
    50     for(int i=1;i<=n;i++){
    51         scanf("%d",&s[i]);
    52     }
    53     get_sa();
    54     get_height();
    55     head=1;tail=0;
    56     for(int i=2;i<=k;i++){
    57         while(height[i]<=height[q[tail]]&&head<=tail)tail--;
    58         q[++tail]=i;
    59     }
    60     ans=height[q[head]];
    61     for(int i=k+1;i<=n;i++){
    62         while(q[head]<=i-k+1&&head<=tail)head++;
    63         while(height[i]<=height[q[tail]]&&head<=tail)tail--;
    64         q[++tail]=i;
    65         ans=max(ans,height[q[head]]);
    66     }
    67     printf("%d",ans);
    68     return 0;
    69 }
  • 相关阅读:
    Android UI中英文自动显示问题
    HTTP通信过程原理
    [转] Protobuf高效结构化数据存储格式
    常用json解析库比较及选择 fastjson & gson
    [转]深入Android内存泄露
    [转]Android 如何有效的解决内存泄漏的问题
    Android View 滚动边界的测量
    Oracle查看表之间的约束
    LINUX学习笔记——LINUX下EXP命令全库备份数据库文件
    LINUX档案权限
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9636883.html
Copyright © 2020-2023  润新知