博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ1743---Musical Theme(+后缀数组二分法)
阅读量:6200 次
发布时间:2019-06-21

本文共 4492 字,大约阅读时间需要 14 分钟。

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 musical timing; but, this programming task is about notes and not timings.
Many composers structure their music around a repeating &qout;theme&qout;, which, being a subsequence of an entire melody, is a sequence of integers in our representation. A subsequence of a melody is a theme if it:

is at least five notes longappears (potentially transposed -- see below) again somewhere else in the piece of musicis disjoint from (i.e., non-overlapping with) at least one of its other appearance(s)

Transposed means that a constant positive or negative value is added to every note value in the theme subsequence.

Given a melody, compute the length (number of notes) of the longest theme.
One second time limit for this problem’s solutions!

Input

The input contains several test cases. The first line of each test case contains the integer N. The following n integers represent the sequence of notes.
The last test case is followed by one zero.

Output

For each test case, the output file should contain a single line with a single integer that represents the length of the longest theme. If there are no themes, output 0.

Sample Input

30

25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
82 78 74 70 66 67 64 60 65 80
0

Sample Output

5

Hint

Use scanf instead of cin to reduce the read time.

Source

LouTiancheng@POJ

求最长不可重叠子串。能够后缀数组+二分解决

先把输入的数字前后两两做差,然后建立后缀数组。二分就可以

/*************************************************************************    > File Name: POJ1743.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年03月31日 星期二 15时43分29秒 ************************************************************************/#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair
PLL;class SuffixArray{ public: static const int N = 20010; int init[N]; int X[N]; int Y[N]; int Rank[N]; int sa[N]; int height[N]; int buc[N]; int size; void clear() { size = 0; } void insert(int n) { init[size++] = n; } bool cmp(int *r, int a, int b, int l) { return (r[a] == r[b] && r[a + l] == r[b + l]); } void getsa(int m = 256) { init[size] = 0; int l, p, *x = X, *y = Y, n = size + 1; for (int i = 0; i < m; ++i) { buc[i] = 0; } for (int i = 0; i < n; ++i) { buc[x[i] = init[i]]++; } for (int i = 1; i < m; ++i) { buc[i] += buc[i - 1]; } for (int i = n - 1; i >= 0; --i) { sa[--buc[x[i]]] = i; } for (l = 1, p = 1; l <= n; m = p, l *= 2) { p = 0; for (int i = n - l; i < n; ++i) { y[p++] = i; } for (int i = 0; i < n; ++i) { if (sa[i] >= l) { y[p++] = sa[i] - l; } } for (int i = 0; i < m; ++i) { buc[i] = 0; } for (int i = 0; i < n; ++i) { ++buc[x[y[i]]]; } for (int i = 1; i < m; ++i) { buc[i] += buc[i - 1]; } for (int i = n - 1; i >= 0; --i) { sa[--buc[x[y[i]]]] = y[i]; } int i; for (swap(x, y), x[sa[0]] = 0, p = 1, i = 1; i < n; ++i) { x[sa[i]] = cmp(y, sa[i - 1], sa[i], l) ?

p - 1 : p++; } if (p >= n) { break; } } } void getheight() { int h = 0; for (int i = 0; i <= size; ++i) { Rank[sa[i]] = i; } height[0] = 0; for (int i = 0; i < size; ++i) { if (h > 0) { --h; } int j = sa[Rank[i] - 1]; for (; i + h < size && j + h < size && init[i + h] == init[j + h]; ++h); height[Rank[i] - 1] = h; } } bool judge(int k) { int maxs = sa[1], mins = sa[1]; for (int i = 1; i < size; ++i) { if (height[i] < k) { maxs = mins = sa[i + 1]; } else { maxs = max(maxs, sa[i + 1]); mins = min(mins, sa[i + 1]); if (maxs - mins > k) { return 1; } } } return 0; } void solve() { int l = 1, r = size; int mid; int ans = 0; while (l <= r) { int mid = (l + r) >> 1; if (judge(mid)) { l = mid + 1; ans = mid; } else { r = mid - 1; } } ++ans; printf("%d\n", ans >= 5 ? ans : 0); } }SA; int val[20010]; int main() { int n; while (~scanf("%d", &n), n) { SA.clear(); for (int i = 1; i <= n; ++i) { scanf("%d", &val[i]); } for (int i = n; i >= 2; --i) { val[i] = val[i] - val[i - 1] + 90; } for (int i = 2; i <= n; ++i) { SA.insert(val[i]); } SA.getsa(); SA.getheight(); SA.solve(); } return 0; }

版权声明:本文博客原创文章。博客,未经同意,不得转载。

你可能感兴趣的文章
Linux平台Oracle多个实例启动说明
查看>>
Asp.Net分页控件
查看>>
chkconfig
查看>>
转载:PHPUnit使用详解
查看>>
Inventor
查看>>
程序员得学会如何微笑
查看>>
部署Nginx服务器
查看>>
maven创建项目命令
查看>>
redis认识
查看>>
程序员的职业寿命
查看>>
社会责任的伦理
查看>>
shell 字典
查看>>
sed学习
查看>>
安装MongoDB遇到的问题
查看>>
server 2008R2所有加入域的计算机不需要按录所有加入域的计算机不需要按ctrl+ALT+DELETE登录...
查看>>
SNMP 协议
查看>>
MySQL生产库主从重新同步操作注意事项
查看>>
回顾2017系列篇(三):UX设计大会,都预示了哪些设计趋势
查看>>
小谈linux使用双网卡实现网络的高可用性
查看>>
我眼中的自动化测试框架设计要点
查看>>