题意:求最少重叠\(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. 基于Nginx简单实现动静分离

    1.首先安装Nginx 2.在Nginx.conf文件中添加如下配置: server{ listen 80; server_name www.lf.com; location ~ (.jpg|.png ...

  2. 数字图像处理实验(15):PROJECT 06-02,Pseudo-Color Image Processing 标签: 图像处理MATLAB 2017-05-27 20:53

    实验要求: 上面的实验要求中Objective(实验目的)部分是错误的. 然而在我拿到的大纲中就是这么写的,所以请忽视那部分,其余部分是没有问题的. 本实验是使用伪彩色强调突出我们感兴趣的灰度范围,在 ...

  3. Luogu 4949 最短距离

    这就是个水题. 一开始想把整个环找出来断开当一条链,然后其他部分正常链剖,两个点之间的路径如果经过环就考虑一下走哪边更快. 但是这样子还是太麻烦了. 我们可以直接断开环上的一条边,然后正常链剖,只要在 ...

  4. python操作Redis缓存

    python操作Redis缓存 https://www.cnblogs.com/guotianbao/p/8683037.html 学习资料:电子书资源 联系邮箱:gmu1592618@gmail.c ...

  5. CLR VIA C# 泛型的协变和逆变

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. Part8-不用内存怎么行_6410内存初始化lesson3

    1.6410地址空间 外设区:从0x70000000-0x7FFFFFFF有256MB 主存储区:从0x00000000-0x6FFFFFFF有1972MB 对于主存储区: 静态存储区可以接我们的NO ...

  7. 手机APP兼容性测试

    兼容性测试方案 兼容性问题 屏幕分辨率兼容性问题 软件(iOS和Android系统版本及不同厂家的定制ROM)兼容性问题 硬件(不同的CPU.内存大小等等)兼容性问题 网络(2G/3G/4G/WIFI ...

  8. 策略(Strategy)模式

    /* * 环境(Context)角色:持有一个Strategy类的引用. * 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现.此角色给出所有的具体策略类所需的接口. * ...

  9. IPMITOOL命令支持列表V2.0

    命令集 命令行格式 命令行说明 User ipmitool -H <IP地址> -I lanplus -U <用户名> -P <密码> user summary 查 ...

  10. WinForm中ListView的使用

    每一行是一个ListViewItem对象,每一项是一个ListViewSubItem对象 样式 整行选择:this.lvDataSourceSearchHistory.FullRowSelect = ...