Musical Theme
Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://poj.org/problem?id=1743

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

题意

让你找到最长的不相交重复子串

题解

后缀数组,跑出height数组之后,然后直接二分然后O(n),check就好了

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 25000
#define mod 10007
#define eps 1e-9
int Num;
char CH[];
//const int inf=0x7fffffff; //нчоч╢С
const int inf=0x3f3f3f3f;
inline ll read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
//************************************************************************************** int s[*maxn];
int a[maxn];
int n;
int sa[maxn], rank[maxn], height[maxn];
int wa[maxn], wb[maxn], wv[maxn], wd[maxn]; int cmp(int *r, int a, int b, int l){
return r[a] == r[b] && r[a+l] == r[b+l];
} void build_sa(int *r, int n, int m){ // 倍增算法 r为待匹配数组 n为总长度 m为字符范围
int i, j, p, *x = wa, *y = wb, *t;
for(i = ; i < m; i ++) wd[i] = ;
for(i = ; i < n; i ++) wd[x[i]=r[i]] ++;
for(i = ; i < m; i ++) wd[i] += wd[i-];
for(i = n-; i >= ; i --) sa[-- wd[x[i]]] = i;
for(j = , p = ; p < n; j *= , m = p){
for(p = , i = n-j; i < n; i ++) y[p ++] = i;
for(i = ; i < n; i ++) if(sa[i] >= j) y[p ++] = sa[i] - j;
for(i = ; i < n; i ++) wv[i] = x[y[i]];
for(i = ; i < m; i ++) wd[i] = ;
for(i = ; i < n; i ++) wd[wv[i]] ++;
for(i = ; i < m; i ++) wd[i] += wd[i-];
for(i = n-; i >= ; i --) sa[-- wd[wv[i]]] = y[i];
for(t = x, x = y, y = t, p = , x[sa[]] = , i = ; i < n; i ++){
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p - : p ++;
}
}
} void calHeight(int *r, int n){ // 求height数组。
int i, j, k = ;
for(i = ; i <= n; i ++) rank[sa[i]] = i;
for(i = ; i < n; height[rank[i ++]] = k){
for(k ? k -- : , j = sa[rank[i]-]; r[i+k] == r[j+k]; k ++);
}
}
int check(int mid)
{
int Minn=sa[],Maxn=sa[];
for(int i=;i<=n;i++)
{
if(height[i]>=mid)
{
Minn=min(sa[i],Minn);
Maxn=max(sa[i],Maxn);
if(Maxn-Minn>mid)
return ;
}
else
Minn=Maxn=sa[i];
}
return ;
}
void init()
{
memset(a,,sizeof(a));
memset(s,,sizeof(s));
memset(sa,,sizeof(sa));
memset(rank,,sizeof(rank));
memset(height,,sizeof(height));
memset(wa,,sizeof(wa));
memset(wb,,sizeof(wb));
memset(wv,,sizeof(wv));
memset(wd,,sizeof(wd));
}
int main()
{
while(cin>>n)
{
if(n==)
break;
init();
for(int i=;i<n;i++)
a[i]=read();
n--;
for(int i=;i<n;i++)
s[i]=a[i+]-a[i]+;
s[n]=;
build_sa(s,n+,);
calHeight(s,n);
int l=,r=n,ans=;
while(l<=r)
{
int mid=(l+r)>>;
if(check(mid))
{
ans=max(ans,mid);
l=mid+;
}
else
r=mid-;
}
if(ans<)
ans=;
else
ans++;
cout<<ans<<endl;
}
}

POJ 1743 Musical Theme 后缀数组 最长重复不相交子串的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. POJ 1743 Musical Theme 后缀数组 不可重叠最长反复子串

    二分长度k 长度大于等于k的分成一组 每组sa最大的和最小的距离大于k 说明可行 #include <cstdio> #include <cstring> #include & ...

  9. poj 1743 Musical Theme 后缀自动机/后缀数组/后缀树

    题目大意 直接用了hzwer的题意 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题."主题&qu ...

随机推荐

  1. 【转】linux驱动开发的经典书籍

    原文网址:http://www.cnblogs.com/xmphoenix/archive/2012/03/27/2420044.html Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书 ...

  2. 【转】cocos2d-x 3.2 Fast TileMap

    概述 在游戏中常常会有丰富的背景元素,如果直接使用大的背景图实现,这会造成资源浪费.TileMap就是为了解决这问题而产生的.Cocos2d-x支持使用Tile地图编辑器创建的TMX格式的地图. Co ...

  3. chrome console js多行输入

    一直以来,Chrome控制台都缺少象IE调试台那样的多行执行模式.  今天意外发现Chrome其实也支持多行模式.默认在Chrome控制台上输入回车后会执行该命令,只需要通过输入Shift+Enter ...

  4. ecshop init.php文件分析

    1.  ecshop init.php文件分析 2.  <?php  3.   4.  /**  5.  * ECSHOP 前台公用文件  6.  * ===================== ...

  5. 升级WordPress

    1. 备份文件 mv wordpress wordpress_3.6 2. 下载新版本 wget http://cn.wordpress.org/wordpress-3.8-zh_CN.zip 3. ...

  6. Activity与Activity之间,Fragment与Fragment之间通过Bundle传值的研究

    一.Fragment与Activity的通讯   在使用fragment的时候,通常的用法都是使用一个activity来管理不同的fragment,所以每个fragment与activity的及时通讯 ...

  7. Alibaba

    题意: 有n个东西在一条路上,已知他们的位置,和能获得他们的最后期限,求能获得n个东西的最小总时间. 分析: 想到了求”未来费用问题", dp[i][j][k]表示获得区间长i起点为j的所有 ...

  8. cocos2d - CCParallaxNode 例子

    CGSize winSize = [[CCDirector sharedDirector] winSize]; CCParallaxNode * node = [CCParallaxNodenode] ...

  9. Asp.net TextBox常规输入验证

    Asp.net TextBox只能输入数字<asp:textbox id="TextBox1" onkeyup="if(isNaN(value))execComma ...

  10. C++调用matlab实例

    这段代码是C++调用matab引擎的过程,代码的目的很简单,在C++中创建一个vector数组,然后将这个vector数组单位化.写这个代码的目的是学些C++与matlab之间的数据交互,以供日后参考 ...