poj 1743 求不可重叠最长字符串
来源:互联网 发布:淘宝联盟结算规则 编辑:程序博客网 时间:2024/05/16 01:31
http://hi.baidu.com/blackstar08/blog/item/6909b391bb308a83a977a429.html
题目大意:
给定一段音乐乐谱,其中的音符用数字表示出来( 范围 [ 1,88 ] ),要求的是这段乐谱的主旋律。所谓的主旋律,就是满足以下三点要求的一段子串:
1、音符的数目至少为5;
2、重复出现在乐谱中的另一个地方;
3、不相互重叠;
而且平移也算重复,比如1 2 3 4 5和6 7 8 9 10是算作重复的,后面的是前面的平移5,然后不互相重叠意思两个主旋律得隔开,比如1 2 3 4 5 6 7 8 9 10
1 2 3 4 5和6 7 8 9 10是紧挨着的,所以不算
解题思路:《后缀数组——处理字符串的有力工具》,求不可重叠最长字符串, 运算时,因为是用计数排序,所以要保证每个数为正。
把后一个旋律减去前一个旋律,要是主旋律重复出现,那么后面减响铃前面形成的间隔差是相同的,那么不可重叠的最长字符串就至少是4了。
然后用后缀数组来处理,详细见上述论文描述。最长公共前缀不小于k的两个后缀,一定是在同一组,按2分来求,逐渐缩小范围。当长度为k时,判断一个组里面sa的最大值和最小值之差是否大于等于k。满足则说明这个k是存在的。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int const maxn = 20010;int n, str[maxn], sa[maxn], rank[maxn], height[maxn], wx[maxn], wy[maxn], c[maxn];inline bool cmp(int *s, int a, int b, int l);void suffix(int *s, int *sa, int n, int m);void cal_height(int *s, int *sa, int n);bool check(int index, int n);int main(){ while(true) { scanf("%d", &n); if(n == 0) break; n--; int a, b; scanf("%d", &a); for(int i = 0; i < n; i++) { scanf("%d", &b); str[i] = b - a + 100; a = b; } str[n] = 0; suffix(str, sa, n + 1, 189); cal_height(str, sa, n); int l = 1, r = n, ans = -1; while(l <= r) { int mid = (l + r) >> 1; if(check(mid, n + 1)) { ans = mid; l = mid + 1; } else r = mid - 1; } if(ans >= 4) printf("%d\n", ans + 1); else printf("0\n"); } return 0;}inline bool cmp(int *s, int a, int b, int l){ return s[a] == s[b] && s[a + l] == s[b + l];}void suffix(int *s, int *sa, int n, int m){ int *x = wx; int *y = wy; int *t, index = 0; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[i] = s[i]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n - 1; i >= 0; i--) sa[--c[s[i]]] = i; for(int j = 1; j <= n; j *= 2, m = index) { index = 0; for(int i = n - j; i < n; i++) y[index++] = i; for(int i = 0; i < n; i++) { if(sa[i] >= j) y[index++] = sa[i] - j; } for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[y[i]]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; t = x; x = y; y = t; x[sa[0]] = rank[sa[0]]= 0; index = 1; for(int i = 1; i < n; i++) { if(j * 2 < n) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? index - 1 : index++; else rank[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? index - 1 : index++; } } }void cal_height(int *s, int *sa, int n){ int k = 0; for(int i = 0; i < n; height[rank[i++]] = k) { if(k != 0) k--; for(int j = sa[rank[i] - 1]; s[i + k] == s[j + k]; k++); }}bool check(int index, int n){ int minv, maxv; minv = maxv = sa[1]; for(int i = 2; i <= n; i++) { if(height[i] >= index && i != n) { minv = min(minv, sa[i]); maxv = max(maxv, sa[i]); } else { if(maxv - minv >= index) return true; minv = maxv = sa[i]; } } return false;}
- poj 1743 求不可重叠最长字符串
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
- 【后缀数组求不可重叠最长重复子串】POJ 1743
- POJ 1743 Musical Theme(后缀数组求不可重叠最长重复子串)
- POJ 1743 Musical Theme(SA 求最长不可重叠重复子串)
- POJ 1743 Musical Theme (后缀数组加二分求不可重叠最长重复子串)
- POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)
- poj 1743 字符串 后缀数组 不可重叠最长重复子串
- POJ 1743 不可重叠最长重复子串
- poj 1743 Musical Theme (不可重叠最长重复子串)
- [POJ]1743 不可重叠最长重复字串 二分答案
- poj 1743 不可重叠最长重复子串
- poj 1743求最长不重叠公共子串
- POJ 1743 后缀数组:求最长不重叠子串
- Poj 1743 Musical Theme (后缀数组 不可重叠最长重复子串)
- poj 1743 Musical Theme (后缀数组 不可重叠最长重复子串)
- poj 1743 Musical Theme(不可重叠的最长重复子串,后缀数组)
- POJ 1743 Musical Theme 不可重叠最长重复字串(后缀数组)
- C++ Exception
- 简洁的拖动表格的列宽
- GPIO_Mode
- STM32 定时器 定时时间的计算
- poj 2063 Investment
- poj 1743 求不可重叠最长字符串
- poj 2756 Autumn is a Genius java解决!!!
- 测试Java的synchronize和ReentrantLock在单线程下的效率
- 在Websphere Portal 7 Client Side Aggregation下运行Spring MVC3 Portlets
- 其它寻址模式与其它指令
- 刚学习,用整数编写了一个RSA加密算法,加深一下理解
- CCNP_route笔记4 EIGRP综合实验
- 使用WebSphere Integration Developer 7开发Business Integration Hello World应用程序
- NS2安装以及configure --enable-debug后的问题解决方法