看来对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. python笔记1

    1.python中的语句块是用缩进表示,并不像C类语言中用{}表示语句块,还有就是语句块的开始貌似是用:表示,然后C类语言中()在python中用"空格"表示了,例如python中 ...

  2. POJ 3696 The Luckiest number (欧拉函数,好题)

    该题没思路,参考了网上各种题解.... 注意到凡是那种11111..... 22222..... 33333.....之类的序列都可用这个式子来表示:k*(10^x-1)/9进而简化:8 * (10^ ...

  3. java Timer类

    java.util 类 Timer java.lang.Object java.util.Timer public class Timerextends Object 一种工具,线程用其安排以后在后台 ...

  4. Javascript 正则表达式_3

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  5. com组件的注册

    错误: 检索 COM 类工厂中 CLSID 为 {79AD7B73-C515-40B4-8B02-CB0F5FA5A1A8} 的组件失败,原因是出现以下错误: 80040154 没有注册类 (异常来自 ...

  6. URAL 1183 Brackets Sequence(DP)

    题目链接 题意 : 给你一串由括号组成的串,让你添加最少的括号使该串匹配. 思路 : 黑书上的DP.dp[i][j] = min{dp[i+1][j-1] (sh[i] == sh[j]),dp[i] ...

  7. C Primer Plus之结构和其他数据形式

    声明和初始化结构指针 声明结构化指针,例如: struct guy * him; 初始化结构指针(如果barney是一个guy类型的结构),例如: him = &barney; 注意:和数组不 ...

  8. MVC中前台如何向后台传递数据------$.get(),$post(),$ajax(),$.getJSON()总结

    一.引言 MVC中view向controller传递数据的时候真心是一个挺让人头疼的一件事情.因为原理不是很懂只看一写Dome,按葫芦画瓢只能理解三分吧. 二.解读Jquery个Ajax函数 $.ge ...

  9. lintcode:最小编辑距离

    最小编辑距离 给出两个单词word1和word2,计算出将word1 转换为word2的最少操作次数. 你总共三种操作方法: 插入一个字符 删除一个字符 替换一个字符 样例 给出 work1=&quo ...

  10. JSTL Tag学习笔记之<fn: />

    在JSTL中也提供了一些标准的函数,但是几乎都是和操作字符串相关的函数,如果需要使用这类函数的话,应该引入下面的taglib: <%@ taglib prefix="fn" ...