题目大意:求可重叠的相同子串数量至少是K的子串最长长度

洛谷传送门

依然是后缀数组+二分,先用后缀数组处理出height

每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个串的长度>=x,

但据说有一种高端做法是把二分换成单调队列,能减少常数,可惜我并没有看懂......

原题好像是哈希的骚操作,但网上的题解好像都是后缀数组......

比上一道男人八题简单多了,我原来的错代码竟然卡过去了70分..

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N 20010
#define inf 0x3f3f3f3f
#define maxn 1000010
using namespace std; int n,len,tot,K;
int a[N],tr[N],sa[N],rk[N],hs[N],h[N];
struct node{int id,val,w;}d[N];
int cmp1(node s1,node s2){return s1.val<s2.val;}
int cmp2(node s1,node s2){return s1.id<s2.id;}
int gint()
{
int rett=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){rett=(rett<<)+(rett<<)+c-'';c=getchar();}
return rett*fh;
}
bool check(int k,int x,int y){
if(x+k>len||y+k>len) return ;
else return (rk[x]==rk[y]&&rk[x+k]==rk[y+k])?:;
}
void get_sa()
{
int cnt=,i;
for(i=;i<=len;i++) hs[a[i]]++;
for(i=;i<=tot;i++) if(hs[i]) tr[i]=++cnt;
for(i=;i<=tot;i++) hs[i]+=hs[i-];
for(i=;i<=len;i++) rk[i]=tr[a[i]],sa[hs[a[i]]--]=i;
for(int k=;cnt<len;k<<=)
{
for(i=;i<=cnt;i++) hs[i]=;
for(i=;i<=len;i++) hs[rk[i]]++;
for(i=;i<=cnt;i++) hs[i]+=hs[i-];
for(i=len;i>=;i--) if(sa[i]>k) tr[sa[i]-k]=hs[rk[sa[i]-k]]--;
for(i=;i<=k;i++) tr[len-i+]=hs[rk[len-i+]]--;
for(i=;i<=len;i++) sa[tr[i]]=i;
for(i=,cnt=;i<=len;i++) tr[sa[i]]=check(k,sa[i],sa[i-])?cnt:++cnt;
for(i=;i<=len;i++) rk[i]=tr[i];
}
}
void get_height()
{
for(int i=;i<=n;i++){
if(rk[i]==) continue;
for(int j=max(,h[rk[i-]]-);;j++)
if(a[i+j-]==a[sa[rk[i]-]+j-]) h[rk[i]]=j;
else break;
}
}
void descrete()
{
sort(d+,d+n+,cmp1);
d[].val=-;
for(int i=;i<=n;i++)
if(d[i].val==d[i-].val)
d[i].w=d[i-].w;
else d[i].w=++tot;
sort(d+,d+n+,cmp2);
for(int i=;i<=n;i++)
a[i]=d[i].w;
}
int check(int ans)
{
int i,cnt=;
for(i=;i<=n;)
{
if(h[i]<ans) {i++;continue;}
for(cnt=;h[i]>=ans&&i<=n;i++)
cnt++;
if(cnt>=K-) return ;
}return ;
} int main()
{
scanf("%d%d",&n,&K);len=n;
for(int i=;i<=n;i++)
d[i].val=gint(),d[i].id=i;
descrete();
get_sa();
get_height();
int l=,r=n,ans=;
while(l<=r){
int mid=(l+r)>>;
if(check(mid)) ans=mid,l=mid+;
else r=mid-;
}printf("%d\n",ans);
return ;
}

BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)的更多相关文章

  1. Poj 3261 Milk Patterns(后缀数组+二分答案)

    Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...

  2. POJ-3261 Milk Patterns,后缀数组+二分。。

                                                        Milk Patterns 题意:求可重叠的至少重复出现k次的最长的字串长. 这题的做法和上一题 ...

  3. poj 3261 Milk Patterns 后缀数组 + 二分

    题目链接 题目描述 给定一个字符串,求至少出现 \(k\) 次的最长重复子串,这 \(k\) 个子串可以重叠. 思路 二分 子串长度,据其将 \(h\) 数组 分组,判断是否存在一组其大小 \(\ge ...

  4. BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

    二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...

  5. [USACO06FEC]Milk Patterns --- 后缀数组

    [USACO06FEC]Milk Patterns 题目描述: Farmer John has noticed that the quality of milk given by his cows v ...

  6. 【题解】回文串 APIO 2014 BZOJ 3676 COGS 1985 Manacher+后缀数组+二分

    这题可以用回文自动机来做,但是我并没有学,于是用Manacher+SA的做法O(nlogn)水过 首先,看到回文串就能想到用Manacher 同样还是要利用Manacher能不重复不遗漏地枚举每个回文 ...

  7. 【poj 3261】Milk Patterns 后缀数组

    Milk Patterns 题意 给出n个数字,以及一个k,求至少出现k次的最长子序列的长度 思路 和poj 1743思路差不多,二分长度,把后缀分成若干组,每组任意后缀公共前缀都>=当前二分的 ...

  8. POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

    Milk Patterns   Description Farmer John has noticed that the quality of milk given by his cows varie ...

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

    题目链接:http://poj.org/problem?id=3261 思路: 后缀数组的很好的一道入门题目 先利用模板求出sa数组和height数组 然后二分答案(即对于可能出现的重复长度进行二分) ...

随机推荐

  1. 漫谈 Google 的 Native Client(NaCl) 技术(二)---- 技术篇(兼谈 LLVM)

    转自:http://hzx5.blog.163.com/blog/static/40744388201172531637729/ 漫谈 Google 的 Native Client(NaCl) 技术( ...

  2. java:递归算法

    JAVA中的递归是只一个方法在(满足条件时(或不满足条件时[这里的判断根据业务的实际需求写]))自己调用自己的方法名,要求参数和方法名一致, 然后根据判断跳出该方法,返回相应的返回值! 实例: 我们要 ...

  3. Trie树检索字符串

    #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct TrieNode ...

  4. echarts在vue里面使用,以及基础配置。

    基础的图表和基础的配置. 效果图如下: 1.安装图表依赖包:npm install echarts 2.在main.js里面 引入echarts import echarts from 'echart ...

  5. 最大团&稳定婚姻系列

    [HDU]   1530 Maximum Clique 1435 Stable Match 3585 maximum shortest distance 二分+最大团 1522 Marriage is ...

  6. BigInteger类(高精度整型)

    位置:java.math.BigInteger 作用:提供高精度整型数据类型及相关操作 一.基本介绍 BigInteger为不可变的任意精度的整数(对象创建后无法改变,每次运算均会产生一个新的对象). ...

  7. linux下添加自定义脚本到开机自启动的方法

    原文链接:http://www.jb51.net/LINUXjishu/183462.html 我的机器有个coreseek服务,但是没加到开启启动中去,导致机房一旦重启了机器,我的服务便不能使用了. ...

  8. iterator遍历list理解

    1.iterator的next()方法返回值,就是你指定的iiterator<>泛型.所以你再强制转换,就可以得到list里的item了,直接是item对象了. 2.list这东西,你ne ...

  9. Shell编程入门(第二版)(上)

    简单的示例Shell程序 示例1. #!/bin/bash #This is to show what a shell script looks like echo "Our first e ...

  10. lpa标签传播算法解说及代码实现

    package lpa; import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class L ...