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

链接:点我
先转化成相邻两项的差值,然后就是找不可重叠重复子串。
做法就是二分答案LEN
然后根据height值进行分组

第一道后缀数组题,测了一下模板

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define MOD 1000000007
const int INF=0x3f3f3f3f;
const double eps=1e-;
typedef long long ll;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
int n,m,tt;
/*
*suffix array
*倍增算法 O(n*logn)
*待排序数组长度为n,放在0~n-1中,在最后面补一个0
*da(str ,n+1,sa,rank,height, , );//注意是n+1;
*例如:
*n = 8;
*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0
*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值
*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值
*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
*
*/
const int MAXN=; char str[MAXN];
int r[MAXN];
int sa[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];//求SA数组需要的中间变量,不需要赋值
//待排序的字符串放在s数组中,从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0,r[n-1]=0
//函数结束以后结果放在sa数组中
bool cmp(int *r,int a,int b,int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int str[],int sa[],int rank[],int height[],int n,int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
//第一轮基数排序,如果s的最大值很大,可改为快速排序
for(i = ;i < m;i++)c[i] = ;
for(i = ;i < n;i++)c[x[i] = str[i]]++;
for(i = ;i < m;i++)c[i] += c[i-];
for(i = n-;i >= ;i--)sa[--c[x[i]]] = i;
for(j = ;j <= n; j <<= )
{
p = ;
//直接利用sa数组排序第二关键字
for(i = n-j; i < n; i++)y[p++] = i;//后面的j个数第二关键字为空的最小
for(i = ; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j;
//这样数组y保存的就是按照第二关键字排序的结果
//基数排序第一关键字
for(i = ; i < m; i++)c[i] = ;
for(i = ; i < n; i++)c[x[y[i]]]++;
for(i = ; i < m;i++)c[i] += c[i-];
for(i = n-; i >= ;i--)sa[--c[x[y[i]]]] = y[i];
//根据sa和x数组计算新的x数组
swap(x,y);
p = ; x[sa[]] = ;
for(i = ;i < n;i++)
x[sa[i]] = cmp(y,sa[i-],sa[i],j)?p-:p++;
if(p >= n)break;
m = p;//下次基数排序的最大值
}
int k = ;
n--;
for(i = ;i <= n;i++)rank[sa[i]] = i;
for(i = ;i < n;i++)
{
if(k)k--;
j = sa[rank[i]-];
while(str[i+k] == str[j+k])k++;
height[rank[i]] = k;
}
}
int rank[MAXN],height[MAXN];
int s[MAXN];
bool check(int n,int k)
{
int Max=sa[],Min=sa[];
for(int i=;i<=n;i++)
{
if(height[i]<k)Max=Min=sa[i];
else
{
if(sa[i]<Min)Min=sa[i];
if(sa[i]>Max)Max=sa[i];
if(Max-Min>k)return true;
}
}
return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(scanf("%d",&n)== && n)
{
for(int i=;i<n;i++)scanf("%d",&s[i]);
for(int i=n-;i>;i--)s[i]=s[i]-s[i-]+;
n--;//减少一个长度
for(int i=;i<n;i++)s[i]=s[i+];
s[n]=;
da(s,sa,rank,height,n,);
int ans=-;
int l=,r=n/;
while(l<=r)
{
int mid=(l+r)/;
if(check(n,mid))
{
ans=mid;
l=mid+;
}
else r=mid-;
}
if(ans<)printf("0\n");
else printf("%d\n",ans+);
}
return ;
}

poj 1743 后缀数组 求最长不重叠重复子串的更多相关文章

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

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

  2. poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 14874   Accepted: 5118 De ...

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

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

  4. Poj 1743——Musical Theme——————【后缀数组,求最长不重叠重复子串长度】

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

  5. poj 1743 后缀数组 最长不重叠子串

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30941   Accepted: 10336 D ...

  6. [八分之一的男人]POJ - 1743 后缀数组 height分组 带详解

    题意:求最长不可重叠的相同差值子串的长度 这道题算是拖了好几个月,现在花了点时间应该搞懂了不少,尝试分析一下 我们首先来解决一个退化的版本,求最长不可重叠的相同子串(差值为0) 比如\(aabaaba ...

  7. POJ 1743 (后缀数组+不重叠最长重复子串)

    题目链接: http://poj.org/problem?id=1743 题目大意:楼教主の男人八题orz.一篇钢琴谱,每个旋律的值都在1~88以内.琴谱的某段会变调,也就是说某段的数可以加减一个旋律 ...

  8. POJ 1743 后缀数组

    题目链接:http://poj.org/problem?id=1743 题意:给定一个钢琴的音普序列[值的范围是(1~88)],现在要求找到一个子序列满足 1,长度至少为5 2,序列可以转调,即存在两 ...

  9. poj2774 Long Long Message 后缀数组求最长公共子串

    题目链接:http://poj.org/problem?id=2774 这是一道很好的后缀数组的入门题目 题意:给你两个字符串,然后求这两个的字符串的最长连续的公共子串 一般用后缀数组解决的两个字符串 ...

随机推荐

  1. 移动端meta声明

    <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --><html lang="zh-cmn-Hans"> ...

  2. A .Gaby And Addition (Gym - 101466A + 字典树)

    题目链接:http://codeforces.com/gym/101466/problem/A 题目: 题意: 给你n个数,重定义两个数之间的加法不进位,求这些数中两个数相加的最大值和最小值. 思路: ...

  3. Git HTTPS 方式自动保存用户名密码

    一行命令搞定: git config --global credential.helper wincred 第一次输入用户名和密码提交,第二次就不需要了 参考: https://help.github ...

  4. python基础之内置异常对象

    前言 什么叫异常?简单来说就是程序运行发生了预计结果之外的情况从而导致程序无法正常运行.而python解释器将一些常见的异常情况在它发生时打包成一个异常对象,我们可以通过捕捉这些异常对象从而进行处理, ...

  5. DAY1-GO初识(概述)

    一.概述 1.特征 1.1.语法简单:规则严谨.保留指针.但默认阻止指针运算.将切片和字典作为内置类型.更好的维护性: 1.2.并发模型:运行时用GOroutine,一个关键字.简单而自然:搭配cha ...

  6. linux下C语言实现的内存池【转】

    转自:http://blog.chinaunix.net/uid-28458801-id-4254501.html 操作系统:ubuntu10.04 前言:     在通信过程中,无法知道将会接收到的 ...

  7. [转载]Firefox插件(plugins)开发实用指南

    转自: http://huandu.me/2010/02/11/595/ Firefox插件可实现强大功能,但其中麻烦事情不少.写这个实用指南首先是为了方便自己记忆,免得以后再次栽倒一些坑里面,如果能 ...

  8. opencv配置过程 (cmake,vs2013,qt 5.4)

    平台及软件: Windows 7 X86 Visual Studio 2013 OpenCV3.0.0 Cmake3.3 1.下载Windows下的安装文件OpenCV-3.0.0.exe,解压,选择 ...

  9. SICP第三章题解

    目录 SICP第三章题解 ex3-17 ex3-18 ex3-19 队列 ex3-21 ex3-22 ex3-24 ex3-25 3.4 并发:时间是一个本质问题 ex3-38 3.4.2 控制并发的 ...

  10. 字典dict常用方法

    字典是列表中常用的方法,我们经常处理字典,字典嵌套,很多复杂的操作都来自于基础,只是改变了样式而已,本质是不变的.下面来看看字典中常用的功能都有那些:     1.clear(self) def cl ...