描述


小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为长度为 N 的数构成的数列。

小Hi在练习过很多曲子以后发现很多作品自身包含一样的旋律。旋律是一段连续的数列,相似的旋律在原数列可重叠。比如在1 2 3 2 3 2 1 中 2 3 2 出现了两次。

小Hi想知道一段旋律中出现次数至少为K次的旋律最长是多少?

输入

第一行两个整数 N和K。1≤N≤20000 1≤K≤N

接下来有 N 个整数,表示每个音的数字。1≤数字≤100

输出

一行一个整数,表示答案。

样例输入

8 2
1
2
3
2
3
2
3
1

样例输出

4

题解


后缀数组主要利用三个映射解决字符串问题

以v[i]表示i~n的后缀字符串

rank[i] 以v[i]为下标,表示v[i]在所有后缀字符串里面的排名

sa[i]以排名为下标,表示排名第i的是sa[i](即某个v[i])

height[i]以排名为下标,表示排名i与排名i-1的后缀字符串的最长公共子串。

对于此题,只需二分答案,可以线性check其正确性,

就是相邻排名的串height都大于mid,那么这一系列的串都满足这个答案,累计出现次数即可。

#include <bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define PI acos(-1)
#define bug puts("here")
#define REP(i,x,n) for(int i=x;i<=n;i++)
#define DEP(i,n,x) for(int i=n;i>=x;i--)
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
inline int read(){
int x=0,f=1;
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;
}
const int N=100005;
int n,m;
int a[N],h[N];
int v[N];
int sa[2][N],rk[2][N];
int p,q,k;
void calsa(int sa[N],int rk[N],int SA[N],int RK[N])
{
for(int i=1; i<=n; i++)v[rk[sa[i]]]=i;
for(int i=n; i; i--)
if(sa[i]>k)
SA[v[rk[sa[i]-k]]--]=sa[i]-k;
for(int i=n-k+1; i<=n; i++)SA[v[rk[i]]--]=i;
for(int i=1; i<=n; i++)
RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
}
void work()
{
p=0,q=1;
for(int i=1; i<=n; i++)v[a[i]]++;
for(int i=1; i<=30; i++)v[i]+=v[i-1];
for(int i=1; i<=n; i++)
sa[p][v[a[i]]--]=i;
for(int i=1; i<=n; i++)
rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
for(k=1; k<n; k<<=1)
{
calsa(sa[p],rk[p],sa[q],rk[q]);
swap(p,q);
}
}
void geth()
{
k=0;
for(int i=1; i<=n; i++)
if(rk[p][i]==1)h[rk[p][i]]=0;
else
{
int j=sa[p][rk[p][i]-1];
while(a[i+k]==a[j+k])k++;
h[rk[p][i]]=k;
if(k>0)k--;
}
}
bool check(int mid){
int res;
REP(i,1,n){
res=1;
while(h[i]>=mid&&i<=n) res++,i++;
if(res>=m) return true;
}
return false;
}
int main(){
n=read();m=read();
REP(i,1,n) a[i]=read();
work();geth();
int l=0,r=n,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}

【HIHOCODER 1403】后缀数组一·重复旋律(后缀数组)的更多相关文章

  1. hihoCoder 1403 后缀数组一·重复旋律(后缀数组+单调队列)

    #1403 : 后缀数组一·重复旋律 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成 ...

  2. hihocoder #1419 : 后缀数组四·重复旋律4

    #1419 : 后缀数组四·重复旋律4 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构 ...

  3. hihocoder #1415 : 后缀数组三·重复旋律3

    #1415 : 后缀数组三·重复旋律3 Time Limit:5000ms Case Time Limit:1000ms Memory Limit:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢 ...

  4. hihocoder #1407 : 后缀数组二·重复旋律2

    #1407 : 后缀数组二·重复旋律2 Time Limit:5000ms Case Time Limit:1000ms Memory Limit:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢 ...

  5. hiho一下123周 后缀数组四·重复旋律

    后缀数组四·重复旋律4 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi ...

  6. hiho一下122周 后缀数组三·重复旋律

    后缀数组三·重复旋律3 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi ...

  7. hiho一下121周 后缀数组二·重复旋律2

    后缀数组二·重复旋律2 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi ...

  8. hiho一下120周 后缀数组一·重复旋律

    后缀数组一·重复旋律 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列. 小Hi ...

  9. HihoCoder1403 后缀数组一·重复旋律1

    后缀数组一·重复旋律 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列. 小Hi ...

  10. hihoCoder 后缀自动机三·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

随机推荐

  1. JDBC连接中Class.forName("")到底干了什么?

    思考了一个问题,Class.forName("***");到底干了什么? 我们知道Class.forName( )静态方法的目的是为了动态加载类,但是一般来说,一个类forName ...

  2. 浅析libuv源码-node事件轮询解析(3)

    好像博客有观众,那每一篇都画个图吧! 本节简图如下. 上一篇其实啥也没讲,不过node本身就是这么复杂,走流程就要走全套.就像曾经看webpack源码,读了300行代码最后就为了取package.js ...

  3. 译:Java 中的正则表达式性能概述

    原文链接:https://www.baeldung.com/java-regex-performance 作者: baeldung 译者:Darren Luo 1. 概述 在本快速教程中,我们将展示模 ...

  4. Linq Enumerable.Distinct方法去重

    Enumerable.Distinct 方法 是常用的LINQ扩展方法,属于System.Linq的Enumerable方法,可用于去除数组.集合中的重复元素,还可以自定义去重的规则. 有两个重载方法 ...

  5. MyBatis学习总结(三)---映射文件及引入方式

    MyBatis的强大,主要原于它强大映射功能,相对其它的jdbc,使用MyBatis,你会发现省掉很多代码.上一篇已经简单做出一个实例.今天就了解一下MyBatis的映射xml文件. 了解上一篇fri ...

  6. String类、StringBuilder类、StringBuffer类

    String类是不可变类,创建了一个String对象后,该String对象中的字符序列不能被改变. StringBuilder是字符序列可变的字符串类,提供了一系列修改字符串的方法. StringBu ...

  7. CentOS7.2上搭建httpbin环境

    CentOS7上搭建httpbin环境 1.安装python31)安装python3.6可能使用的依赖yum -y install openssl-devel bzip2-devel expat-de ...

  8. 机器学习经典算法之SVM

    SVM 的英文叫 Support Vector Machine,中文名为支持向量机.它是常见的一种分类方法,在机器学习中,SVM 是有监督的学习模型. 什么是有监督的学习模型呢?它指的是我们需要事先对 ...

  9. Python:numpy数组转换为json格式

    在python中,如何将一个numpy数组转换为json格式? 这是最近遇到的一个问题,做个笔记. 假设arr为numpy数组,将其转换为json格式: 总体思想是①首先转换为python的list, ...

  10. Adobe登陆出现Access denied解决方法

    当我安装好Adobe Acrobat Reader DC时,想要登陆Adobe账号时被Access denied. 一般说需要梯子,然而本人亲测这种方法不行(香港主机,全局模式下). 一个简单有效的方 ...