题目大意:

* 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。 * “主题”是整个音符序列的一个子串,它需要满足如下条件: * 1.长度至少为5个音符 * 2.在乐曲中重复出现(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值。) * 3.重复出现的同一主题不能有公共部分。

 

分析:也是看的论文才做的这道题,学了4天的后缀数组,终于A掉一道题了,啥也不说了,都是眼泪(怎么做可以看看论文,说的很详细)。

 

代码如下:

===============================================================================================================

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std; const int MAXN = 2e4+;
const int BaseNum = ; struct SuffixArr
{
int text[MAXN], tempx[MAXN], tempy[MAXN];
int sum[MAXN], rank[MAXN], sa[MAXN], heigh[MAXN];
int *x, *y, N, MaxId; void Insert(int mus[], int len)
{
N = len, MaxId = ;
x = tempx, y=tempy; for(int i=; i<N; i++)
{
x[i] = text[i] = mus[i];
y[i] = i;
}
}
void BaseSort()
{
for(int i=; i<MaxId; i++)
sum[i] = ;
for(int i=; i<N; i++)
sum[ x[ y[i] ] ] += ;
for(int i=; i<MaxId; i++)
sum[i] += sum[i-];
for(int i=N-; i>=; i--)
sa[ --sum[ x[ y[i] ] ] ] = y[i];
}
bool OK(int i, int len)
{
if(sa[i]+len>N || sa[i-]+len>N)
return false;
if(y[sa[i]] != y[sa[i-]] || y[sa[i]+len] != y[sa[i-]+len])
return false; return true;
}
void Build_Sa()
{
BaseSort(); for(int len=; len<N; len<<=)
{
int id = ; for(int i=N-len; i<N; i++)
y[id++] = i;
for(int i=; i<N; i++)if(sa[i]>=len)
y[id++] = sa[i] - len; BaseSort();
swap(x, y); x[ sa[] ] = id = ; for(int i=; i<N; i++)
{
if(OK(i, len) == true)
x[ sa[i] ] = id;
else
x[ sa[i] ] = ++id;
} MaxId = id+; if(MaxId >= N)break;
}
}
void GetHeight()
{
for(int i=; i<N; i++)
rank[ sa[i] ] = i; for(int k=,i=; i<N; i++)
{
if(!rank[i])
{
k = heigh[] = ;
continue;
}
if(k)k--; int pre = sa[ rank[i]- ]; while(text[pre+k] == text[i+k])
k++;
heigh[rank[i]] = k;
}
}
}; struct SuffixArr suf;
int music[MAXN]; bool Find(int k)
{
int Min, Max; Min = Max = suf.sa[]; for(int i=; i<suf.N; i++)
{
if(suf.heigh[i] < k)
Min = Max = suf.sa[i];
else
{
Min = min(Min, suf.sa[i]);
Max = max(Max, suf.sa[i]); if(Max-Min > k)
return true;
}
} return false;
} int main()
{
int i, N; while(scanf("%d", &N), N)
{
for(i=; i<N; i++)
{
scanf("%d", &music[i]);
if(i)music[i-] = music[i-]-music[i]+BaseNum;
}
music[N-] = ; suf.Insert(music, N);
suf.Build_Sa();
suf.GetHeight(); int L=, R=N/, ans=-; while(L <= R)
{
int Mid = (L+R)>>; if(Find(Mid) == true)
{
L = Mid + ;
ans = Mid;
}
else
R = Mid - ;
} printf("%d\n", ans+);
} return ;
}

Musical Theme - poj 1743(求最大不重叠重复子串)的更多相关文章

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

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

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

    求不可重叠最长重复子串 对于height[i]定义为sa[i]和 sa[i-1]的最长公共前缀 这个最长公共前缀的值肯定是最大的 证明: 设rank[j] < rank[k], 则不难证明后缀j ...

  3. Musical Theme POJ - 1743 后缀数组

    A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...

  4. poj 1961 (求字符串中的重复子串)

    Sample Input 3aaa12aabaabaabaab0Sample Output Test case #12 23 3 Test case #22 2 //aa有2个a6 2 //aabaa ...

  5. POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)

    永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...

  6. poj1743 Musical Theme 后缀数组的应用(求最长不重叠重复子串)

    题目链接:http://poj.org/problem?id=1743 题目理解起来比较有困难,其实就是求最长有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1 ...

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

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

  8. ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】

    SETI Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statist ...

  9. hdu_2668 Daydream O(n)求最长不重复子串

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2668 Daydream Time Limit: 2000/1000 MS (Java/Others)  ...

随机推荐

  1. CSS Display(显示) 与 Visibility(可见性)

    display属性设置一个元素应如何显示,visibility属性指定一个元素应可见还是隐藏. Box 1 Box 2 Box 3 隐藏元素 - display:none或visibility:hid ...

  2. 水题(素数表)NYOJ素数距离

                描述 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度.如果左右有等距离长度素数,则输出左侧的值及相应距离. 如果输入的整数本身就是素数,则输 ...

  3. HDU3591找零,背包

    题目大概的意思就是:小强用硬币买东西,硬币有N种,面值为Vi,店家有各种硬币都有无限个,而小强只有Ci个(分别对应Vi) 问最小交易硬币数,就是一个有找零的背包问题啦. 我的上一篇博客跟这hdu359 ...

  4. C#应用程序中读取Oracle数据库

    前言 最近的任务就是开发了一个功能,要从供应商那边读取数据,然后拿过来,处理以后放到我们自己的数据库中.供应商那边是Oracle数据库,其实不管什么数据我想都差不多,于是我就开始了.由于在家里写的博客 ...

  5. 更改input【type=file】样式

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. word2007在试图打开文件时遇到错误解决方法

    当您尝试在 Microsoft Office Word 2007 中打开 .docx 文件时,该文件打不开.此外,您还会收到以下错误消息: Word 在试图打开文件时遇到错误.请尝试下列方法:* 检查 ...

  7. 移动端触摸滑动插件Swiper

    移动端触摸滑动插件Swiper 04/02/2015 一.了解Swiper 目前移动端项目一般都需要具有触屏焦点图的效果,如果你也需要实现这一功能的话,Swiper是一个不错的选择. 1.他不需要加载 ...

  8. 2的N次方

    /**编程精确计算2的N次方.(N是介于100和1000之间的整数)*//*问题代码:#include<stdio.h>#include<math.h>int main(){ ...

  9. 根据http协议传送数据

    发送的内容: [50 4f 53 54 20 2f 64 65 78 2f 66 69 72 65 70 6f 77 65 72 20 48 54 54 50 2f 31 2e 31 0d 0a 43 ...

  10. servlet监听器实现在线人数统计

    一.准备知识 servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层. filter:fi ...