POJ 1743:Musical Theme(后缀数组+二分)
题意
有N个音符的序列来表示一首乐曲,每个音符都是1到88范围内的整数,现在要找一个重复的主题。“主题”是整个音符序列的一个子串,它需要满足如下条件:
- 长度至少为5个音符。
- 在乐曲中重复出现。(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值)
- 重复出现的同一主题不能有公共部分。
思路
论文里面出现的题目。
因为加上和减去同一个整数值,就可以作差,因为减出来可能是个负数,因此需要+88.
二分答案,转化为是否存在两个长度为k的子串是相同的,且不重叠。
将height数组根据k分组,使得每组的后缀之间的height值都大于等于k,有希望成为最长公共前缀不小于k的两个后缀在同一组。
要使得两个串不重叠,只要判断同一组里面最大的sa值和最小的sa值的差大于等于k,这样就可以不重叠了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 11;
int t1[N], t2[N], c[N], s[N], str[N], Hash[N], sa[N], rak[N], heigth[N], n;
bool cmp(int *r, int a, int b, int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
}
void DA(int s[], int n, int m) {
n++;
int i, j, p, *x = t1, *y = t2;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = s[i]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
for(j = 1; j < n; j <<= 1) {
p = 0;
for(i = n - j; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[sa[0]] = 0;
for(i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p - 1 : p++;
if(p >= n) break;
m = p;
}
n--;
int k = 0;
for(i = 0; i <= n; i++) rak[sa[i]] = i;
for(i = 0; i < n; i++) {
if(k) k--;
j = sa[rak[i]-1];
while(s[i+k] == s[j+k]) k++;
heigth[rak[i]] = k;
}
}
bool check(int k) {
int mi = INF, ma = -INF;
for(int i = 2; i <= n; i++) {
if(heigth[i] >= k) {
mi = min(mi, min(sa[i], sa[i-1]));
ma = max(ma, max(sa[i], sa[i-1]));
if(ma - mi >= k) return 1;
} else {
mi = INF, ma = -INF;
}
} return 0;
}
int main() {
while(scanf("%d", &n), n) {
for(int i = 0; i < n; i++) scanf("%d", &s[i]);
for(int i = 0; i < n; i++) s[i] = s[i+1] - s[i] + 88;
int m = 177;
n--;
s[n] = 0;
DA(s, n, m);
int l = 0, r = n, ans = l;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid)) l = mid + 1, ans = mid;
else r = mid - 1;
}
if(ans < 4) puts("0");
else printf("%d\n", ans + 1);
}
return 0;
}
POJ 1743:Musical Theme(后缀数组+二分)的更多相关文章
- Poj 1743 Musical Theme (后缀数组+二分)
题目链接: Poj 1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- POJ 1743 Musical Theme ——后缀数组
[题目分析] 其实找最长的不重叠字串是很容易的,后缀数组+二分可以在nlogn的时间内解决. 但是转调是个棘手的事情. 其实只需要o(* ̄▽ ̄*)ブ差分就可以了. 背板题. [代码] #include ...
- POJ 1743 Musical Theme 后缀数组 最长重复不相交子串
Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...
- poj 1743 Musical Theme (后缀数组+二分法)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 16162 Accepted: 5577 De ...
- [poj 1743] Musical Theme 后缀数组 or hash
Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...
- POJ 1743 Musical Theme ( 后缀数组 && 最长不重叠相似子串 )
题意 : 给 n 个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等. 分析 : 根据题目对于 “ 相似 ” 串的定义,我们可以将原 ...
- POJ.1743.Musical Theme(后缀数组 倍增 二分 / 后缀自动机)
题目链接 \(Description\) 给定一段数字序列(Ai∈[1,88]),求最长的两个子序列满足: 1.长度至少为5 2.一个子序列可以通过全部加或减同一个数来变成另一个子序列 3.两个子序列 ...
- POJ 1743 Musical Theme 后缀数组 不可重叠最长反复子串
二分长度k 长度大于等于k的分成一组 每组sa最大的和最小的距离大于k 说明可行 #include <cstdio> #include <cstring> #include & ...
- POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)
洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...
随机推荐
- SAAS是否能实现人在家工作的梦想?
在过去的十年,在人们的工作环境的巨大变化已经发生,越来越多的人选择在家工作. 高租金的办公室,络,快速宽带的广泛应用.这些因素都使得远程办公成为了人们工作中密不可分的一种方式.使用普通手机和办公操作系 ...
- PHP模拟POST提交数据并获得返回值之CURL方法(使用PHP extension,然后使用php_curl.dll,很不错)
今天公司做个东西,需要条用同事的接口,我的代码和他的代码不在同一个域下,但是都是子域. a.ifensi.com与b.ifensi.com的关系. 我需要传递一个关联数组过去,他那边给我返回一个jso ...
- sql学习目录
sql like N'%...%' 在C#里的写法 sql 循环 随机数创建数据 使用StringBuilder与SqlParameter 跨库查询数据 sql 多列求和 sql SCOPE_IDEN ...
- 2018-4-25-- 2.在sublime3里安装git插件并连接GitHub
1.配置全局参数 Git的主要配置包括用户名.邮箱的设置.以及生成SSH密钥公钥等. 首先运行一下的命令设置git提交代码时自己的用户信息. 2.在sublime3里使用时需要配置push.defau ...
- 如何计算memcache的容量
在容量足够的情况下,当然是越大越好,但这样会造成浪费.不考虑这种情况.我们一般的情况是: memcache集群一开始创建会根据存储的数据量与访问量进行容量大小的估算.再算一个20%的冗余. 在网站快速 ...
- C#实现判断图形文件格式的方法
1. 通过文件的扩展名来判断.这种方法比较简单,但若是有人故意改下文件扩展名,这种方法就不起作用了. 2.通过C#自身提供的方法来进行判断(判断某种确定的图片类型). 示例如下: bool isJPG ...
- R3 HOOK OpenProcess 的问题
unit HookAPI; //Download by http://www.codefans.net interface uses Windows, Classes; function Locate ...
- 凤年读史27:普鲁士vs德意志
孙宇 普鲁士,是熟悉历史的人都知道的一个名词,它与德国关系密切.似乎在某些情境中,普鲁士就是德国,而在另一些场合,普鲁士和德国又不一样,有所区别.那么普鲁士到底是什么?它和德国到底是什么关系? 普鲁士 ...
- C++ 王者归来:对编程语言的需求总结为四个:效率,灵活,抽象,生产率(C++玩的是前三个,Java和C#玩的是后两个)
Why C++ ? 王者归来(转载) 因为又有人邀请我去Quora的C2C网站去回答问题去了,这回是 关于 @laiyonghao 的这篇有点争议的博文<2012 不宜进入的三个技术点>A ...
- 一、OpenScenGraph环境搭建
1.OpenSceneGraph 3.4.0 网址 http://www.openscenegraph.org/ github源码地址 https://github.com/openscenegr ...