POJ 1743 Musical Theme Hash + 二分

原本是《后缀数组——处理字符串的有力工具》论文中的第一道例题,发现自己智商不够,一个下午没有看懂后缀数组= =,就用hash写了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;
typedef long long LL;
const int maxn = 20000 + 5;
const int mod = 65536;
const int phc = 1e9 + 7;
int num[maxn], val[maxn], n;
int head[mod], nxt[maxn], pos[maxn], sz;
LL hval[maxn];
LL hc[maxn], pw[maxn];

bool ok(int k) {
	memset(head, -1, sizeof(head));
	sz = 0;
	for (int i = k; i <= n; i++) {
		LL nowval = hc[i] - hc[i - k] * pw[k], nowpos = nowval & (mod - 1);
		for (int j = head[nowpos]; ~j; j = nxt[j]) {
			if (nowval == hval[j] && i - pos[j] >= k) {
				return true;
			}
		}
		pos[sz] = i; hval[sz] = nowval;
		nxt[sz] = head[nowpos]; head[nowpos] = sz++;
	}
	return false;
}

int main() {
	pw[0] = 1;
	for (int i = 1; i < maxn; i++) {
		pw[i] = pw[i - 1] * phc;
	}
	while (scanf("%d", &n), n) {
		for (int i = 1; i <= n; i++) scanf("%d", &num[i]);
		for (int i = 1; i < n; i++) val[i] = num[i + 1] - num[i] + 100;
		n--;
		hc[0] = 0;
		for (int i = 1; i <= n; i++) {
			hc[i] = hc[i - 1] * phc + val[i];
		}
		int l = 1, r = n, ans = 0;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (ok(mid)) {
				l = mid + 1; ans = mid + 1;
			}
			else r = mid - 1;
		}
		if (ans < 5) ans = 0;
		printf("%d\n", ans);
	}
}

  

时间: 2024-11-05 07:36:02

POJ 1743 Musical Theme Hash + 二分的相关文章

Poj 1743 Musical Theme (后缀数组+二分)

题目链接: Poj  1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现(或者经过调转出现,调转是主题同时加上或者减去同一个整数) 3:重复主题不能重叠 解题思路: 求调转重复出现的子串,那么主题之间的差值一定是不变的.可以求文本串s中相邻两个数的差值,重新组成一个新的文本串S,然后找S后缀串中最长公共不重叠前缀.rank相邻的后缀串,公共前缀一定最长,但是有可能重叠.

POJ 1743 Musical Theme (后缀数组)

题目大意: 刚才上88个键弹出来的音符. 如果出现重复的,或者是高一个音阶的重复的都算. 思路分析: 具体可以参考训练指南222. height数组表示按照排序后的sa最近的两个后缀的最长前缀. 将height 分块.然后二分答案,二分答案之后去判断是否满足. 要考虑到不重合,还有大于5. 所以二分的时候要从5开始,然后判断的时候要加一个 up - down >len #include <cstdio> #include <iostream> #include <alg

poj 1743 Musical Theme(男人八题&amp;后缀数组第一题)

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 17298   Accepted: 5939 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the

POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It

poj 1743 Musical Theme(后缀数组)

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30544   Accepted: 10208 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the

Poj 1743——Musical Theme——————【后缀数组模板题】

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22499   Accepted: 7679 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the

POJ 1743 Musical Theme【SAM】

POJ1743 Musical Theme 要找长度\(\ge 5\)且出现次数\(\ge 2\)并且第一次出现和最后一次出现不重叠的最长子串. 题目条件中,如果对于两个串,在一个串的每个数上都加上相同的数之后可以得到另一个串,那么这个两个串可以被是相同的. 首先我们先得到差分数组,然后要求的就是差分数组中长度\(\ge 4\)且出现次数\(\ge 2\)并且第一次出现和最后一次出现不重叠的最长子串 我们需要知道的是每个等价类中终点的最左端和最右端的位置,即(\(firstpos,lastpos

POJ 1743 Musical Theme(后缀数组+二分答案)

[题目链接] http://poj.org/problem?id=1743 [题目大意] 给出一首曲子的曲谱,上面的音符用不大于88的数字表示, 现在请你确定它主旋律的长度,主旋律指的是出现超过一次, 并且长度不小于5的最长的曲段,主旋律出现的时候并不是完全一样的, 可能经过了升调或者降调,也就是说, 是原来主旋律所包含的数字段同时加上或者减去一个数所得, 当然,两段主旋律之间也是不能有重叠的,现在请你求出这首曲子主旋律的长度, 如果不存在请输出0. [题解] 首先要处理的是升调和降调的问题,由

POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)

Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of music