题意:求最少重叠\(k\)次的重复子串的最大长度

子串长度问题依然是二分枚举,可以观察出重叠的一定是sa排序中连续的

之前想出一种判断要\(n^2\)的方法,没有考虑到后面肯定会连续出现的情况

(大概想法是枚举重复中的最大\(lcp\)(和之前定义的\(lcp\)有所区别),若存在\(k\)个\((i-j)<=lcp\)既为真←好像很不靠谱的样子)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iin(a) scanf("%d",&a)
#define lin(a) scanf("%lld",&a)
#define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a)
#define s1(a) scanf("%s",a+1)
#define print(a) printf("%lld",(ll)a)
#define enter putchar('\n')
#define blank putchar(' ')
#define println(a) printf("%lld\n",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int maxn = 1e5+11;
const int oo = 0x3f3f3f3f;
const double eps = 1e-7;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int str[maxn],n;
struct SA{
int Rank[maxn],sa[maxn],tsa[maxn],A[maxn],B[maxn];
int cntA[maxn],cntB[maxn];
int height[maxn],best[maxn][30],n;//height[i]:第sa[i]与sa[i-1]的cp
void get(int nn){
n=nn;
rep(i,0,23333) cntA[i]=0;
rep(i,1,n) cntA[str[i]]++;
rep(i,1,23333) cntA[i]+=cntA[i-1];
rrep(i,n,1) sa[cntA[str[i]]--]=i;
Rank[sa[1]]=1;
rep(i,2,n){
if(str[sa[i]]==str[sa[i-1]]){
Rank[sa[i]]=Rank[sa[i-1]];
}else{
Rank[sa[i]]=1+Rank[sa[i-1]];
}
}
for(int l=1;Rank[sa[n]]<n;l<<=1){
rep(i,1,n) cntA[i]=cntB[i]=0;
rep(i,1,n) cntA[A[i]=Rank[i]]++;
rep(i,1,n) cntB[B[i]=(i+l<=n?Rank[i+l]:0)]++;
rep(i,1,n) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
rrep(i,n,1) tsa[cntB[B[i]]--]=i;
rrep(i,n,1) sa[cntA[A[tsa[i]]]--]=tsa[i];
Rank[sa[1]]=1;
rep(i,2,n){
bool flag=A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]];
flag=!flag;
Rank[sa[i]]=Rank[sa[i-1]]+flag;
}
}
}
void ht(){
int j=0;
rep(i,1,n){
if(j) j--;
while(str[i+j]==str[sa[Rank[i]-1]+j]) j++;
height[Rank[i]]=j;
}
}
void rmq(){
rep(i,1,n) best[i][0]=height[i];
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)-1<=n;j++){
best[j][i]=min(best[j][i-1],best[j+(1<<(i-1))][i-1]);
}
}
}
int query(int l,int r){
if(l==r)return -oo;
if(l>r)swap(l,r);
l++;
int k=log2(r-l+1);
return min(best[l][k],best[r-(1<<k)+1][k]);
}
}sa;
int a[maxn],k;
bool check(int x){
int cnt=0;bool flag=1;
for(int i=1;i<=n;i++){
if(sa.height[i]>=x){
cnt++;
if(flag){
cnt++;
flag=0;
}
if(cnt>=k)return 1;
}else{
cnt=0;
flag=1;
}
}
return 0;
}
int main(){
while(cin>>n>>k){
rep(i,1,n) str[i]=a[i]=read()+1;
sort(a+1,a+1+n);
int m=unique(a+1,a+1+n)-a-1;
rep(i,1,n) str[i]=lower_bound(a+1,a+1+m,str[i])-a;//保留1
str[n+1]=0;
sa.get(n);
sa.ht();
int l=1,r=n,mid,ans=0;
while(l<=r){
mid=(l+r)>>1;
if(check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
println(ans);
}
return 0;
}

POJ - 3261 后缀数组 height应用的更多相关文章

  1. POJ 3261 后缀数组

    题目链接:http://poj.org/problem?id=3261 题意:约翰注意到奶牛产奶的之类是不断变化的,虽然他不能预测从当天到下一天的变化情况但是他知道变化是有规律的,牛奶的质量由一个整数 ...

  2. poj 3261 后缀数组 找反复出现k次的子串(子串能够重叠)

    题目:http://poj.org/problem?id=3261 仍然是后缀数组的典型应用----后缀数组+lcp+二分 做的蛮顺的,1A 可是大部分时间是在调试代码.由于模板的全局变量用混了,而自 ...

  3. [八分之一的男人]POJ - 1743 后缀数组 height分组 带详解

    题意:求最长不可重叠的相同差值子串的长度 这道题算是拖了好几个月,现在花了点时间应该搞懂了不少,尝试分析一下 我们首先来解决一个退化的版本,求最长不可重叠的相同子串(差值为0) 比如\(aabaaba ...

  4. Milk Patterns POJ - 3261 后缀数组

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On furthe ...

  5. POJ 3261 (后缀数组 二分) Milk Patterns

    这道题和UVa 12206一样,求至少重复出现k次的最长字串. 首先还是二分最长字串的长度len,然后以len为边界对height数组分段,如果有一段包含超过k个后缀则符合要求. #include & ...

  6. [poj 3261]后缀数组+滑窗最小值

    题目链接:http://poj.org/problem?id=3261 这个是可以交叉的重复串,所以用height就可以了,但是题目说让重复k次以上,也就是直接做一个k-1长度的滑窗最小值,从这些最小 ...

  7. poj 3261 后缀数组 可重叠的 k 次最长重复子串

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16430   Accepted: 7252 Ca ...

  8. POJ 3261 后缀数组+二分

    思路: 论文题- 二分+对后缀分组 这块一开始不用基数排序 会更快的(其实区别不大) //By SiriusRen #include <cstdio> #include <cstri ...

  9. poj 3693 后缀数组 重复次数最多的连续重复子串

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8669   Acc ...

随机推荐

  1. pandas dataframe 满足条件的样本提取

    pandas 的dataframe 对 数据查询可以通过3种方式 . 预备知识: 1. pandas 的索引和label都是从0开始的计数的 2. 时间切片都是左闭右开的. [5:6,:]  只会输出 ...

  2. GridSearchCV scoring 参考

    http://scikit-learn.org/stable/modules/model_evaluation.html Scoring parameter: Model-evaluation too ...

  3. osm2pgsql windows “illegal option -W” error

    新版本不支持 解决: 修改pg_hba.conf的METHOD为trust 参考:http://stackoverflow.com/questions/15510428/osm2pgsql-windo ...

  4. JMS-消息中间件的应用01-基本概念-来自慕课学习-新手学习

    什么是JMS? Java消息服务(Java Message Service),即JMS,是一个java平台中关于面向消息中间件的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信. ...

  5. HTTP Modules versus ASP.NET MVC Action Filters

    from:http://odetocode.com/blogs/scott/archive/2011/01/17/http-modules-versus-asp-net-mvc-action-filt ...

  6. LightOJ 1284 Lights inside 3D Grid (数学期望)

    题意:在一个三维的空间,每个点都有一盏灯,开始全是关的.现在每次随机选两个点,把两个点之间的全部点,开关都按一遍,问k次过后开着的灯的期望数量: 析:很容易知道,如果一盏灯被按了奇数次,那么它肯定是开 ...

  7. 桥梁(Bridge)模式

    桥梁(Bridge)模式:桥梁模式是一个非常有用的模式,也是比较复杂的一个模式.熟悉这个模式对于理解面向对象的设计原则,包括"开-闭"原则(OCP)以及组合/聚合复用原则(CARP ...

  8. Javascript脚本 :Function 对象的定义和使用

    javascript  Function 对象的定义 创建函数的语法:var myFunction=new Function(arg1,arg2,...agrN,body);agrN 为函数的参数,b ...

  9. 【转】Android系统概览

    这篇文章其实原文叫 <老罗的Android之旅>导读PPT 是罗升阳的博客,我觉得用“Android系统概览”作为标题更贴切些,对于在应用层已经开发了一段时间的人来说,读完之后会有很多体会 ...

  10. Nexus 私有仓库

    Nexus3.6和Nexus2.x安装不同,2.x版本需要安装服务,再启动.而3.6版本则更加简单. 步骤如下: jdk环境:1.8 Nexus3.6解压(注意,路径不要带空格及中文),解压后有两个文 ...