Musical Theme
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 22499   Accepted: 7679

Description

A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of musical timing; but, this programming task is about notes and not timings. 
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 input contains several test cases. The first line of each test case contains the integer N. The following n integers represent the sequence of notes. 
The last test case is followed by one zero. 

Output

For each test case, the output file should contain a single line with a single integer that represents the length of the longest theme. If there are no themes, output 0.

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

Use scanf instead of cin to reduce the read time.

Source

 
 
题目大意:让你找最长的音乐主题,主题:1.需要最少由5个音符组成 2.音符之间不重叠 3.同一个主题可以是由同时升或降的一段音调组成(如 1 2 3 4 5 10 11 12 13 14 15 是一个音乐主题)。
 
解题思路:相邻的音符之间做差,再加上一个不会让跟差值做和后出现零或者负值的整数,在最后赋值为0,表示结束位置。然后就直接模板套就ok了。
 
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
using namespace std;
const int maxn = 1e5+200;
const int INF = 0x3f3f3f3f;
int a[maxn],s[maxn];
int sa[maxn], t[maxn], t2[maxn], c[maxn];
int rank[maxn], height[maxn];
void build_sa(int n, int m){
int i,*x = t, *y = t2;
//初始化,基数排序
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = s[i]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1){
int p = 0;
for(i = n-k; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = 1; x[sa[0]] = 0;
for(i =1; i < n; i++)
x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] ==y[sa[i]+k] ? p-1:p++;
if(p >= n) break;
m = p;
}
return ;
}
void getheight(int n) { int i, j, k = 0;
for(i = 0; i < n; i++) {
rank[sa[i]] = i;
}
for(i = 0; i < n; i++) {
if(k) k--;
int j = sa[rank[i]-1];
while(s[i+k] == s[j+k]){
k++;
}
height[rank[i]] = k;
}
}
bool check(int mid , int n){
int mi=INF , mx = 0;
for(int i=2;i<=n+1;i++){
if(i==n+1 || height[i] < mid){
// printf("%d %d %d\n",i,height[i],mid);
mi = min(mi, sa[i-1]);
mx = max(mx, sa[i-1]);
if(mx - mi >= mid){
return true;
}
mx = 0;mi = INF;
}
else if(height[i] >= mid){
mi= min(mi,sa[i-1]);
mx= max(mx,sa[i-1]);
}
}
return false;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF && n ){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
if(n<10){
puts("0");
continue;
}
for(int i=0;i<n-1;i++){
s[i]=a[i+1]-a[i]+89;
}
s[n-1]=0;
// for(int i=0;i<=n;i++){
// printf("%d ",s[i]);
// }puts("");
build_sa(n,200);
// for(int i=0;i<=n;i++){
// printf("%d %d-+-+-+\n",i,sa[i]);
// }
getheight(n);
// for(int i=0;i<n;i++){
// printf("%d %d------------------\n",i,height[i]);
// }
int l=4,r=n/2+1,mid;
int ans = 0;
while(l<=r){
mid=(l+r)/2;
if(check(mid , n)){
l=mid+1;
ans=max(mid,ans);
}else{
r=mid-1;
}
}
if(ans<4) puts("0");
else printf("%d\n",ans+1);
}
return 0;
} /*
10
1 1 1 1 1 1 1 1 1 1 */

  

Poj 1743——Musical Theme——————【后缀数组,求最长不重叠重复子串长度】的更多相关文章

  1. poj 1743 后缀数组 求最长不重叠重复子串

    题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题. “主题”是整个音符序列的一个子串,它需要满足如下条件:1 ...

  2. Poj 1743 Musical Theme (后缀数组+二分)

    题目链接: Poj  1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...

  3. POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

    Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...

  4. poj 1743 Musical Theme (后缀数组+二分法)

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16162   Accepted: 5577 De ...

  5. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  6. [poj 1743] Musical Theme 后缀数组 or hash

    Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...

  7. POJ 1743 Musical Theme ( 后缀数组 && 最长不重叠相似子串 )

    题意 : 给 n 个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等. 分析 :  根据题目对于 “ 相似 ” 串的定义,我们可以将原 ...

  8. POJ 1743 Musical Theme ——后缀数组

    [题目分析] 其实找最长的不重叠字串是很容易的,后缀数组+二分可以在nlogn的时间内解决. 但是转调是个棘手的事情. 其实只需要o(* ̄▽ ̄*)ブ差分就可以了. 背板题. [代码] #include ...

  9. POJ.1743.Musical Theme(后缀数组 倍增 二分 / 后缀自动机)

    题目链接 \(Description\) 给定一段数字序列(Ai∈[1,88]),求最长的两个子序列满足: 1.长度至少为5 2.一个子序列可以通过全部加或减同一个数来变成另一个子序列 3.两个子序列 ...

随机推荐

  1. .net关于应用程序缓存的一些疑惑

    疑惑:获取缓存后强制转换为实体对象传递给前台,如果前台对这个实体对象中属性更改的话缓存中的数据也随之改变,为啥??? 首先是创建缓存的方法: /// <summary> /// 创建缓存项 ...

  2. 在Action获取Scope对象

    引言:在前面的Action操作中,关键就是Action中的exectue方法,但是此方法并没有request.session.application等对象作为参数,自然就不能利用这些对象来操作.下面我 ...

  3. [poj1737]Connected Graph(连通图计数)

    题意:输出题中带有$n$个标号的图中连通图的个数. 解题关键: 令$f(n)$为连通图的个数,$g(n)$为非联通图的个数,$h(n)$为总的个数. 则$f(n) + g(n) = h(n)$ 考虑标 ...

  4. C++中对象的常引用

    直接传递对象名 用对象名做函数参数时,在函数调用时将建立一个新的对象,它是形参对象的拷贝. ================下面给出一个直接传递对象名的例子程序1.1================= ...

  5. Could not get lock /var/lib/dpkg/lock - open 解决方法

    无法获得锁 /var/lib/dpkg/lock E: Could not get lock /var/lib/dpkg/lock - open (11 Resource temporarily un ...

  6. Leetcode:9. Palindrome Number

    这题要求不能使用额外的空间,我也就没做,看了下别人的代码,挺有意义的一道题目,出坏了. 解题思路:从右往左颠倒过来,看看这个值和原来的x值是不是一样,最后还要注意像20这种情况,也是的 public ...

  7. 1.4 如何防止sql注入

    如何防止sql注入   1.检查变量数据类型和格式 如果你的SQL语句是类似where id={$id}这种形式,数据库里所有的id都是数字,那么就应该在SQL被执行前,检查确保变量id是int类型: ...

  8. 【并发编程】Future模式添加Callback及Promise 模式

    Future Future是Java5增加的类,它用来描述一个异步计算的结果.你可以使用 isDone 方法检查计算是否完成,或者使用 get 方法阻塞住调用线程,直到计算完成返回结果.你也可以使用  ...

  9. [CentOS7] parted用于磁盘分区(同时支持GPT和MBR分区表)

    声明:本文主要总结自:鸟哥的Linux私房菜-第七章.Linux 磁碟與檔案系統管理,如有侵权,请通知博主 fdisk支持MBR分区表,gdisk支持GPT分区表,而parted支持两者 不知道为什么 ...

  10. 消息队列RabbitMQ、缓存数据库Redis

    1.RabbitMQ消息队列 1.1 RabbitMQ简介 AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中 ...