看来对height数组进行分段确实是个比较常用的技巧。

题意:

一个主题是可以变调的,也就是如果这个主题所有数字加上或者减少相同的数值,可以看做是相同的主题。

一个主题在原串中至少要出现两次,而且一定要有不相交的两次。

因为说了可以变调,所以我们处理每相邻两项的差值,这样就得到n-1个数字。然后找最大的不相交重复的连续子序列即可。

找这样的子序列还是要二分子序列的长度k,然后根据k对height进行分段,如果某一段的最大的sa值与最小的sa值相差超过k的话便符合要求。

然后强调一下几个容易出错的地方:

  • 前面说一定要超过k才行,下面解释下为什么等于k是不可以的。比如说n=5, 序列为 0 3 8 11 16.求出相邻两项的差值为3 5 3 5,很明显子序列3 5是一个不相交的重复序列,但是第一个3 5 对应原序列的0 3 8,第二个3 5 对应原序列的 8 11 16. 显然,这有重叠的部分了。
  • 我们在求出相邻两项差值的序列中找到最长不相交子序列后,假设长度为k,那么对应原序列中子序列的长度为k + 1
 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
const int INF = ;
int n; struct SuffixArray
{
int s[maxn];
int sa[maxn];
int rank[maxn];
int height[maxn];
int t[maxn], t2[maxn], c[maxn];
int n; void clear() { n = ; memset(sa, , sizeof(sa)); } void build_sa(int m)
{
int i, *x = t, *y = t2;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[i] = s[i]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= )
{
int 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++) 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];
swap(x, y);
p = ; x[sa[]] = ;
for(i = ; i < n; i++)
x[sa[i]] = y[sa[i]]==y[sa[i-]] && y[sa[i]+k]==y[sa[i-]+k] ? p - : p++;
if(p >= n) break;
m = p;
}
} void build_height()
{
int i, j, k = ;
for(i = ; i < n; i++) rank[sa[i]] = i;
for(i = ; i < n; i++)
{
if(k) k--;
j = sa[rank[i] - ];
while(s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
}
}; SuffixArray sa; bool ok(int len)
{
int Max, Min;
Max = Min = sa.sa[];
for(int i = ; i < n; i++)
{
if(sa.height[i] < len) Max = Min = sa.sa[i];
else
{
Max = max(Max, sa.sa[i]);
Min = min(Min, sa.sa[i]);
if(Max - Min > len) return true;
}
}
return false;
} int solve()
{
int L = , R = n / , M;
while(L < R)
{
M = (L + R + ) / ;
if(ok(M)) L = M;
else R = M - ;
}
return L;
} int main()
{
//freopen("in.txt", "r", stdin); while(scanf("%d", &n) == && n)
{
sa.clear(); int pre, now; scanf("%d", &pre);
n--;
for(int i = ; i < n; i++)
{
scanf("%d", &now);
sa.s[i] = now - pre + ;
pre = now;
}
sa.s[n] = ;
sa.n = n;
sa.build_sa();
sa.build_height();
int ans = solve();
printf("%d\n", ans >= ? ans + : );
} return ;
}

代码君

POJ 1743 (后缀数组 二分) Musical Theme的更多相关文章

  1. Musical Theme POJ - 1743 后缀数组

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

  2. POJ 1743 后缀数组

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

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

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

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

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

  5. POJ 2774 后缀数组 || 二分+哈希

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 35607   Accepted: 14 ...

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

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

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

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

  8. POJ 3261 (后缀数组 二分) Milk Patterns

    这道题和UVa 12206一样,求至少重复出现k次的最长字串. 首先还是二分最长字串的长度len,然后以len为边界对height数组分段,如果有一段包含超过k个后缀则符合要求. #include & ...

  9. POJ 3261 后缀数组+二分

    思路: 论文题- 二分+对后缀分组 这块一开始不用基数排序 会更快的(其实区别不大) //By SiriusRen #include <cstdio> #include <cstri ...

随机推荐

  1. 基于jQuery很牛X的批量上传插件

    上传功能应该是每个网站必备的工具之一,因此出现了出现了很多各式各样的上传插件! 本文基于个人经验和使用从插件的:交互体验,易用性,文档,美观度出发,为大家推荐三款很NX的批量上传插件! 下面三款插件的 ...

  2. 为 PHP 开发者准备的 12 个调试工具

    PHP是在实践中发展迅速并被最多使用的脚本语言:包含了诸如详细的文档.庞大的社区.无数可使用的脚本及支持框架等许多特性.PHP提供的这些特性使得它比Python或Ruby等脚本语言更容易上手. 为构建 ...

  3. C# 使用 AutoResetEvent 或 ManualResetEvent 同步两个线程

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. Unity3D之Assetbundle

    原地址: Unity3D之Assetbundle 有几个地方需要注意下 1.如何解决资源重复加载的问题 2.初始化了就直接出现在场景中了  感觉怪怪的 3.标红的地方要注意下  prefab上挂载的脚 ...

  5. PHP几个函数

    pack: 数据装入一个二进制字符串 http_build_query: 将数组转化成URL GET参数的形式. get_class:返回对象的类名,注:即使是在父类方法中调用也是返回子类的类名. g ...

  6. POJ3469 Dual Core CPU(最小割)

    题意:给你n个模块,每个模块在A核花费为ai,在B核跑花费为bi,然后由m个任务(ai,bi,wi),表示如果ai,bi不在同一个核上跑,额外的花费为wi,求最小的花费. 一开始想的时候以为是费用流, ...

  7. WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发

    今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出 ...

  8. run fsck manually

    就出现unexpected inconsistency run fsck manually这个问题了. 磁盘出问题,需要用 Fsck修复... 解决方案: 在命令行输入#mount | grep ”o ...

  9. try catch语句在VC下的处理

    使用VC编译QT程序碰到一个问题: 我在.h文件里定义:    LoadingWidget* w;然后.cpp文件里定义: void MyClass::ModifyTask(){    // w = ...

  10. wrong number of arguments,java方法反射时数组参数的坑

    java方法中只有一个参数是数组,反射的时候我们不能想当然的传歌数组进去,传数组进去的时候表示多个参数. 两个数组不是一个意思啊. 我们应该把数组转为objet,这样才表示一个参数. import j ...