POJ-1743 Musical Theme(最长不可重叠子串,后缀数组+二分)
Many composers structure their music around a repeating &qout;theme&qout;, which, being a subsequence of an entire melody, is a sequence of integers in our representation. A subsequence of a melody is a theme if it:
- is at least five notes long
- appears (potentially transposed -- see below) again somewhere else in the piece of music
- is disjoint from (i.e., non-overlapping with) at least one of its other appearance(s)
Transposed means that a constant positive or negative value is added to every note value in the theme subsequence.
Given a melody, compute the length (number of notes) of the longest theme.
One second time limit for this problem's solutions!
Input
The last test case is followed by one zero.
Output
Sample Input
30
25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
82 78 74 70 66 67 64 60 65 80
0
Sample Output
5
Hint
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。“主题”是整个音符序列的一个子串,它需要满足如下条件:
1、长度至少为5个音符。
2、在乐曲中重复出现。(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值)
3、重复出现的同一主题不能有公共部分。
思路:后缀数组。求出任意相邻音符的差值,然后把问题转化为不可重叠最长重复子串,用后缀数组来做。先二分答案,把题目变成判定性问题:判断是否存在两个长度为k的子串是相同的,且不重叠。
先不考虑重叠,重复子串的长度要大于等于k,也就是一个区间内的height值都大于等于k,当出现height小于k则重新定位。
再来考虑重叠,我们知道了一个区间的height都大于等于k,如果存在两个后缀距离大于k,那么可以肯定存在两个长度为k的子串是相同的,且不重叠。
参考代码:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<string>
using namespace std;
#define clr(a,val) memset(a,val,sizeof a)
const int maxm=;
int N;
struct SuffixArray{
int s[maxm];
int sa[maxm],height[maxm],rank[maxm],n;
int t[maxm*],t2[maxm*];
long long cnt[maxm];
void build_sa(int m){
int i,*x=t,*y=t2;
for(i=;i<m;i++) cnt[i]=;
for(i=;i<n;i++) cnt[x[i]=s[i]]++;
for(i=;i<m;i++) cnt[i]+=cnt[i-];
for(i=n-;i>=;i--) sa[--cnt[x[i]]]=i;
for(int k=,p=;k<n;k <<=)
{
p=;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=;i<m;i++) cnt[i]=;
for(i=;i<n;i++) cnt[x[y[i]]]++;
for(i=;i<m;i++) cnt[i]+=cnt[i-];
for(i=n-;i>=;i--) sa[--cnt[x[y[i]]]]=y[i];
swap(x,y);
p=;x[sa[]]=;
for(i=;i<n;i++)
if(y[sa[i-]]==y[sa[i]]&&y[sa[i-]+k]==y[sa[i]+k])
x[sa[i]]=p-;
else x[sa[i]]=p++;
if(p>=n)
break;
m=p;
}
}
void build_height()
{
int k=;
for(int i=;i<n;i++) rank[sa[i]]=i;
for(int i=;i<n;i++)
{
if(k) k--;
if(!rank[i]) continue;
int j=sa[rank[i]-];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
} SA; bool check(int key)
{
int tMax = SA.sa[];
int tMin = SA.sa[];
for (int i = ; i<=N; ++i)
{
if (SA.height[i] < key) tMax = tMin = SA.sa[i];
else
{
if(SA.sa[i] < tMin) tMin = SA.sa[i];
if(SA.sa[i] > tMax) tMax = SA.sa[i];
if(tMax - tMin > key) return true;
}
}
return false;
}
int main()
{
while(~scanf("%d",&N)&&N)
{
SA.n=N;
int t,k;N--;
scanf("%d",&t);
for(int i=;i<N;++i)
{
scanf("%d",&k);
SA.s[i]=k-t+;
t=k;
}
SA.s[N]=;
SA.build_sa();
SA.build_height();
int L=,R=N/,ans=;
while(L<=R)
{
int mid=L+R>>;
if(check(mid)) ans=mid,L=mid+;
else R=mid-;
}
printf("%d\n",(ans>=? ans+:));
} return ;
}
POJ-1743 Musical Theme(最长不可重叠子串,后缀数组+二分)的更多相关文章
- POJ 1743 - Musical Theme 最长不重叠重复子串
题意: 给出一列数据,问你其中重复的最长连续子串的长度 但是有要求: 1. 长度至少为 5 . 2. 两串可以不相等,但两串每个对应位置的数字相减差值固定 (即 ...
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- Poj 1743 Musical Theme (后缀数组+二分)
题目链接: Poj 1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...
- URAL 1297 最长回文子串(后缀数组)
1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...
- POJ 1743 Musical Theme 【后缀数组 最长不重叠子串】
题目冲鸭:http://poj.org/problem?id=1743 Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Su ...
- poj 1743 Musical Theme (后缀数组+二分法)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 16162 Accepted: 5577 De ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- POJ 1743 Musical Theme ——后缀数组
[题目分析] 其实找最长的不重叠字串是很容易的,后缀数组+二分可以在nlogn的时间内解决. 但是转调是个棘手的事情. 其实只需要o(* ̄▽ ̄*)ブ差分就可以了. 背板题. [代码] #include ...
随机推荐
- Arduino 配置 ESP8266环境
Arduino 配置 ESP8266环境 将 http://arduino.esp8266.com/stable/package_esp8266com_index.json 添加到 [附加开发板管理器 ...
- iOS核心动画高级技巧-1
1. 图层树 图层的树状结构 巨妖有图层,洋葱也有图层,你有吗?我们都有图层 -- 史莱克 Core Animation其实是一个令人误解的命名.你可能认为它只是用来做动画的,但实际上它是从一个叫做L ...
- Arduino驱动ILI9341彩屏(一)——颜色问题
最近在淘宝的店铺上淘到了一块ILI9341的彩色液晶屏,打算研究一下如何使用. 淘宝店铺购买屏幕之后有附源代码可供下载,代码质量惨不忍睹,各种缩进不规范就不说了,先拿来试一下吧. 这是淘宝店铺代码的核 ...
- Session,Cookie的区别
1. 为什么要有session的出现? 答:是由于网络中http协议造成的,因为http本身是无状态协议,这样,无法确定你的本次请求和上次请求是不是你发送的.如果要进行类似论坛登陆相关的操作,就实现不 ...
- ubuntu 16.04源码编译OpenCV教程 | compile opencv on ubuntu 16.04
本文首发于个人博客https://kezunlin.me/post/15f5c3e8/,欢迎阅读! compile opencv on ubuntu 16.04 Series Part 1: comp ...
- python--数字灯管
import turtle import time def drawLine(draw): #绘制单段数码管 turtle.pendown() if draw else turtle.penup() ...
- es6 every的使用
let arr2 =[1,3,5,7,9,10]; //arr2.every() 数组里面所有的元素都有符合条件,才返回true var b =arr2.every(function (val,ind ...
- scrapy知识补充--scrapy shell 及Spider
什么是scrapy shell? Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试xpath或css表达是,来查看他们的工作方式,方便爬取页面中的数据 ...
- Java工作流系统-CCBPM如何自动升级?
关键词:工作流快速开发平台 工作流流设计 业务流程管理 asp.net 开源工作流 bpm工作流系统 java工作流主流框架 自定义工作流引擎驰骋工作流引擎ccflow和jflow的升级 ...
- yum运行报错:/usr/lib64/python2.7/site-packages/pycurl.so: undefined symbol: CRYPTO_num_locks
是因为yum动态库使用了新安装libcurl库导致的.使用ldd查看动态库依赖关系: ldd /usr/lib64/python2.7/site-packages/pycurl.so 删除动态库配置中 ...