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

来源:互联网 发布:生辰八字宝宝起名软件 编辑:程序博客网 时间:2024/06/03 13:33

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)

3025 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 1882 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)

3025 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 1882 78 74 70 66 67 64 60 65 80

输出格式
输出文件应该包含一个单独的行,其中一个整数表示最长的主题的长度。如果没有主题,输出为0。
样例输出(文件theme.out)
5


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


/*ID : mcdonne1LANG : 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;}



原创粉丝点击