POJ1743 Musical Theme(二分+后缀数组)
题目大概是给n个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等。
这题是传说中楼教主男人八题之一,虽然已经是用后缀数组解决不可重叠最长重复子串的经典题了。。但其实没那么简单,题目数据不强,网上一些代码都是不正确的。
- 首先把问题转化成重复子串的问题:把原串每一位都与前一位相减。这样得出的新串如果有两个长度为n的子串相同,那么它们对应在原串的长度n+1的子串也就相似。
- 所以接下来要求的就是这个新串不可“重叠”最长重复子串——问题就在这儿,这不只是要求不可重叠,还要求两个子串要隔至少一个位置,因为如果两个子串靠在一起这样反应到原串那两个子串各自的首尾是重合的。
比如数据:9 1 1 1 1 1 1 1 1 1
隔至少一个位置其实只要原本的if(mx-mm>=k)改成if(mx-mm>k)就行了。
最后大概描述一下不可重叠最长重复子串的解法:
- O(logn)二分枚举子串长度,判断解是否成立
- O(n)判断长度是否成立:把互相之间LCP大于等于长度的分为一组,这通过个扫一遍height即可,因为后缀是有序的,相邻的后缀间的LCP必定的极大的;接下来就找到每个组里后缀sa值最大和最小的,如果差值大于(等于)k就成立,因为这样小下标的后缀沿着LCP下去走k步才不会盖到大下标的后缀。
另外,说一下二分枚举解,二分具体写法很多吧,也不知道正不正确。。我那样的写法我发现:
- 如果是求最小解,mid要取floor,即mid=(left+right)/2
- 如果是求最大解,mid要取ceil,即mid=(left+right+1)/2
看起来好像是这个样子的。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 22222
#define INF (1<<30)
int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b] && r[a+l]==r[b+l];
}
int sa[MAXN],rank[MAXN],height[MAXN];
void SA(int *r,int n,int m){
int *x=wa,*y=wb; for(int i=; i<m; ++i) ws[i]=;
for(int i=; i<n; ++i) ++ws[x[i]=r[i]];
for(int i=; i<m; ++i) ws[i]+=ws[i-];
for(int i=n-; i>=; --i) sa[--ws[x[i]]]=i; int p=;
for(int j=; p<n; j<<=,m=p){
p=;
for(int i=n-j; i<n; ++i) y[p++]=i;
for(int i=; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
for(int i=; i<n; ++i) wv[i]=x[y[i]];
for(int i=; i<m; ++i) ws[i]=;
for(int i=; i<n; ++i) ++ws[wv[i]];
for(int i=; i<m; ++i) ws[i]+=ws[i-];
for(int i=n-; i>=; --i) sa[--ws[wv[i]]]=y[i];
swap(x,y); x[sa[]]=; p=;
for(int i=; i<n; ++i) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
} for(int i=; i<n; ++i) rank[sa[i]]=i;
int k=;
for(int i=; i<n-; height[rank[i++]]=k){
if(k) --k;
for(int j=sa[rank[i]-]; r[i+k]==r[j+k]; ++k);
}
} int n,a[MAXN],r[MAXN];
bool isok(int k){
bool flag=;
int mx=-INF,mm=INF;
for(int i=; i<=n; ++i){
if(height[i]>=k){
mm=min(mm,min(sa[i],sa[i-]));
mx=max(mx,max(sa[i],sa[i-]));
if(mx-mm>k) return ;
}else{
mx=-INF,mm=INF;
}
}
return ;
}
int main(){
while(~scanf("%d",&n) && n){
for(int i=; i<n; ++i) scanf("%d",a+i);
--n;
for(int i=; i<n; ++i) r[i]=a[i+]-a[i]+;
r[n]=;
SA(r,n+,);
int l=,r=n>>;
while(l<r){
int mid=l+r+>>;
if(isok(mid)) l=mid;
else r=mid-;
}
if(l>=) printf("%d\n",l+);
else printf("%d\n",);
}
return ;
}
POJ1743 Musical Theme(二分+后缀数组)的更多相关文章
- POJ-1743 Musical Theme,后缀数组+二分!
Musical Theme 人生第一道后缀数组的题,采用大众化思想姿势极其猥琐. 题意:给你n个 ...
- poj1743 Musical Theme【后缀数组】【二分】
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 35044 Accepted: 11628 D ...
- POJ1743 Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串
A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...
- POJ 1743 Musical Theme 二分+后缀数组
Musical Theme Description A musical melody is represented as a sequence of N (1<=N<=20000)no ...
- poj1743 Musical Theme(后缀数组|后缀自动机)
[题目链接] http://poj.org/problem?id=1743 [题意] 求不可重叠最长重复子串. 2015-11-27 [思路] 1) 据题意处理字符串 ...
- 【POJ1743】Musical Theme(后缀数组)
[POJ1743]Musical Theme(后缀数组) 题面 洛谷,这题是弱化版的,\(O(n^2)dp\)能过 hihoCoder 有一点点区别 POJ 多组数据 题解 要求的是最长不可重叠重复子 ...
- POJ 1743 Musical Theme(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1743 [题目大意] 给出一首曲子的曲谱,上面的音符用不大于88的数字表示, 现在请你确定它主旋律的长度,主旋律指的是出现超过一次, ...
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- POJ 1743 Musical Theme 【后缀数组 最长不重叠子串】
题目冲鸭:http://poj.org/problem?id=1743 Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Su ...
- P2743(poj1743) Musical Themes[差分+后缀数组]
P2743 乐曲主题Musical Themes(poj1743) 然后呢这题思路其实还是蛮简单的,只是细节特别多比较恶心,忘记了差分带来的若干疏漏.因为转调的话要保证找到相同主题,只要保证一段内相对 ...
随机推荐
- 【alpha冲刺】随笔合集
Daily Scrum Meeting 第一天 [Alpha]Daily Scrum Meeting第一次 第二天 [Alpha]Daily Scrum Meeting第二次 第三天 [Alpha]D ...
- Alpha冲刺——Day2
一.合照 二.项目燃尽图 三.项目进展 图形界面基本完成 接口文档框架完成,接下来将会不断细化填充 登录界面向服务器请求数据进行ing 四.明日规划 1.注册登录接口能够完成 2.研究idea实现获得 ...
- Bate版敏捷冲刺报告--day0
1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285) Git链接:https://github.com/WHUSE2017/C-team 2 ...
- Java基础 成员变量的继承与覆盖
通过继承可以得到父类的成员变量,子类的成员变量包括从父类继承的成员变量(包括从祖先类中继承的成员变量)以及子类中重新定义的成员变量.本次介绍内容包括:可以继承哪些成员?如果子类和父类出现了相同的成员变 ...
- verilog学习笔记(3)_task/case小例子及其tb
module ex_case `timescale lns/1ns module ex_case( input wire rst_n, input wire sclk, output reg [7:0 ...
- 构建微服务开发环境7————使用Github管理项目代码的版本
[内容指引] 1.注册GitHub帐号: 2.下载Github Desktop客户端: 3.macOS安装Github Desktop客户端: 4.windows安装Github Desktop客户端 ...
- WIN10系统触摸板快捷键
快捷的手势操作,有时候会让人脱离鼠标,只要不是非用不可的情况,基本上这些常用手势就能让我们摆脱鼠标携带不便或者桌子地方小的烦恼.iOS上的快捷手势很是受欢迎,win10上却鲜有人知晓,尤其是非开发人员 ...
- api-gateway实践(07)新服务网关 - 手动发布
应用地址:http://10.110.20.191:8080/api-gateway-engine/ 一.准备工作 1.xshell登陆云主机 1.1.配置链接 1.2.链接成功 1.3.关闭防火墙 ...
- Bootstrap 做一个简单的母版页
随便搭的一个母版页,不太好看,只是为了看效果....请勿吐槽. 效果如图: 一.新建母版页,引入Bootstrap相关js文件 <link href="../css/bootstrap ...
- C# 文件操作类大全
C# 文件操作类大全 时间:2015-01-31 16:04:20 阅读:1724 评论:0 收藏:0 [点我收藏+] 标签: 1.创建文件夹 //usin ...