C++——【USACO 5.1.3】——Musical Themes

44 篇文章 0 订阅

Musical Themes
Brian Dean

A musical melody is represented as a sequence of N (1 <= N <= 5000) 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 "theme", 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 long
  • appears (potentially transposed -- see below) again somewhere else in the piece of music
  • is 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!

PROGRAM NAME: theme

INPUT FORMAT

The first line of the input file contains the integer N. Each subsequent line (except potentially the last) contains 20 integers representing the sequence of notes. The last line contains the remainder of the notes, potentially fewer than 20.

SAMPLE INPUT (file theme.in)

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

OUTPUT FORMAT

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 OUTPUT (file theme.out)

5
[The five-long theme is the last five notes of the first line and the first five notes of the second] 


音乐主题


一个音乐的旋律被表示为一个长度为N (1<=N<=5000)的序列,它是范围1~88中的整数。每一个都代表钢琴上的一个键。不幸的是,这种旋律的表达忽略了音乐时间的概念;但是,这个编程任务是关于notes而不是计时。
许多作曲家围绕着一个重复的“主题”来构建他们的音乐,这是一个完整的旋律的序列,我们用
一系列整数序列表示。一个旋律的子序列主题的要求:

至少有5个音符
在音乐的另一个地方出现了(有可能被调换了位置)
不相交,不重叠
转置意味着在主题序列中增加了一个常数的正或负的值。
给定一个旋律,计算最长主题的长度(音符的数量)。
项目名称 :  theme
输入格式
输入文件的第一行包含整数n,每个后续行(可能是最后一个)包含20个整数。最后一行包含注释的其余部分,可能少于20个。
示例输入(文件theme.in)

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。
样例输出(文件theme.out)
5


5个长主题是第一行的最后5个音符和第二行前5个音符


/*
ID : mcdonne1
LANG : C++
TASK : theme
*/

#pragma GCC optimize("O3")

#include <fstream>
#include <cstring>

int n, ans;
short f[5003], next[5003];

inline short read () {
	short i = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) i = i * 10 + c - 48, c = getchar();
	return i;
}

int main () {
	freopen ("theme.in", "r", stdin);
	freopen ("theme.out", "w", stdout);
	f[1 + (n = read())] = -1e+3;
	for (int i = 1; i <= n; i++) f[i] = read();
	for (int i = n; i >= 1; i--) f[i] -= f[i - 1];
	for (int i = n - 4; i >= 4; i--) {
		memset (next, 0, sizeof(next));
		for (int j = i + 1, k = next[j - i]; j <= n; j++) {
			while (k and f[j] != f[i + k]) k = next[k];
			if (f[j] == f[i + k]) next[j - i + 1] = k + 1;
		}
		for (int j = 0, k = 0; j < i - 1; j++)
		{
			while (k and f[j] != f[i + k]) k = next[k];
			if (f[j] == f[i + k]) ans = std::max(ans, ++k + 1);
		}
	}
	printf("%d\n", ans >= 5 ? ans : 0);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值