当前位置: 首页 > news >正文

【HIHOCODER 1403】后缀数组一·重复旋律(后缀数组)

描述


小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;
}

转载于:https://www.cnblogs.com/zsyacm666666/p/7769167.html

相关文章:

  • C#中如何将DataTable中的数据写入Excel
  • 打印机的一些高级设置
  • Qt4--FormLayout
  • 通用服务器桩-Receiver使用说明文档
  • linux ftp 实例
  • 啥活都得干好
  • python框架对比
  • 最快的搭建PXE
  • DBImport v3.0 中文版发布-支持各大数据库数据互导(IT人员必备工具)
  • C语言的第一堂课
  • linux定时任务的设置
  • WPF命中测试示例(二)——几何区域命中测试
  • heartbeat-ldirectord的配置
  • LLVM 与 Clang 介绍
  • 实例讲解如何查找某个对象的定义情况
  • Elasticsearch 参考指南(升级前重新索引)
  • Hibernate【inverse和cascade属性】知识要点
  • JavaScript中的对象个人分享
  • js作用域和this的理解
  • Mysql5.6主从复制
  • Node 版本管理
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • React Native移动开发实战-3-实现页面间的数据传递
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 驱动程序原理
  • 实现简单的正则表达式引擎
  • 数组大概知多少
  • 如何在招聘中考核.NET架构师
  • 选择阿里云数据库HBase版十大理由
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​人工智能书单(数学基础篇)
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #NOIP 2014#Day.2 T3 解方程
  • (ros//EnvironmentVariables)ros环境变量
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (分布式缓存)Redis持久化
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • ***测试-HTTP方法
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .NET 常见的偏门问题
  • .pyc文件是什么?
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @Builder用法
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)