码迷,mamicode.com
首页 > 编程语言 > 详细

[POJ1743] Musical Theme (后缀数组)

时间:2015-11-20 19:43:16      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:

  • 题目概述:

  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: 

  1. is at least five notes long 
  2. appears (potentially transposed -- see below) again somewhere else in the piece of music 
  3. 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. 

  给你一段乐章,乐章由n个音符组成,这些音符由1..88的整数表示。现在你需要找出最长的一段旋律,使得这一段旋律至少有5个音符,至少出现过两次,且这两次的位置不相交(如果两段旋律经过变调后是一样的,那么这两段旋律可以看成出现过两次)。

  • 输入格式:

  输入包含多组数据,每组数据的第一行包括一个整数n,表示乐章的长度。接下来一行包括n个整数,表示每个音符。

  • 输出格式:

  输出一个整数,表示满足题意的最长的旋律的长度。

  • 样例输入:

  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

  • 样例输出:

  5

  • 思路:

  表示...字符串的题真心鬼畜。半天%完罗穗骞的《后缀数组——处理字符串的有力工具》后,彻底滚粗(kmp,心中永远的痛)。

  先做完了UOJ#35的模板题,又调了半天,内心是崩溃的。

  于是开始lg这道题。

  

  一道后缀自动机的模板题。用相邻两个数的差构造新的串,对新串用后缀数组lg一下,然后二分一下求不相交子串的最大长度。

  注意n=1的情况(可以和n<10的情况一起判了)。

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int MAXN = 20005;
 6 int s[MAXN], sx[MAXN], sy[MAXN], ssum[MAXN], sa[MAXN], rk[MAXN], h[MAXN];
 7 inline bool cmp(int* y, int i, int j, int k) {
 8     return y[i] == y[j] && y[i + k] == y[j + k];
 9 }
10 
11 void getsa(int n, int m) {
12     int i, j, p, *x = sx, *y = sy;
13     for(i = 0; i < m; ++i) ssum[i] = 0;
14     for(i = 0; i < n; ++i) ++ssum[x[i] = s[i]];
15     for(i = 1; i < m; ++i) ssum[i] += ssum[i - 1];
16     for(i = n - 1; ~i; --i) sa[--ssum[x[i]]] = i;
17     for(p = j = 1; p < n; j <<= 1, m = p) {
18         for(p = 0, i = n - j; i < n; ++i) y[p++] = i;
19         for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j;
20         for(i = 0; i < m; ++i) ssum[i] = 0;
21         for(i = 0; i < n; ++i) ++ssum[x[y[i]]];
22         for(i = 1; i < m; ++i) ssum[i] += ssum[i - 1];
23         for(i = n - 1; ~i; --i) sa[--ssum[x[y[i]]]] = y[i];
24         swap(x, y); x[sa[0]] = 0;
25         for(p = i = 1; i < n; ++i) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
26     }
27 }
28 
29 void geth(int n) {
30     int j, k = 0;
31     for(int i = 1; i <= n; ++i) rk[sa[i]] = i;
32     for(int i = 0; i < n; h[rk[i++]] = k)
33         for(k ? k-- : 0, j = sa[rk[i] - 1]; s[i + k] == s[j + k]; ++k);
34 }
35 
36 int solve(int x, int n) {
37     int i = 2, minh, maxh;
38     while(1) {
39         while(i <= n && h[i] < x) ++i;
40         if(i > n) break;
41         maxh = minh = sa[i - 1];
42         while(i <= n && h[i] >= x) {
43             minh = min(minh, sa[i]); maxh = max(maxh, sa[i++]);
44         }
45         if(maxh - minh > x) return true;
46     }
47     return false;
48 }
49 
50 int main() {
51     int n;
52     while(~scanf("%d", &n) && n) {
53         memset(sx, 0, sizeof(sx));
54         memset(sy, 0, sizeof(sy));
55         memset(sx, 0, sizeof(sa));
56         memset(ssum, 0, sizeof(ssum));
57         for(int i = 0; i < n; ++i) scanf("%d", s + i);
58         if(--n < 9) { puts("0"); continue; }
59         for(int i = 0; i < n; ++i) s[i] = s[i + 1] - s[i] + 90;
60         s[n] = 0;
61         getsa(n + 1, 200); geth(n);
62         int l = 1, r = (n >> 1) + 1;
63         while(l < r - 1) {
64             int mid = l + r >> 1;
65             if(solve(mid, n)) l = mid;
66             else r = mid;
67         }
68         printf("%d\n", l < 4 ? 0 : r);
69     }
70     return 0;
71 }

  (话说论文里的变量名好奇怪)

  

  抱歉博客更晚了,以后应该可以按时更新。

[POJ1743] Musical Theme (后缀数组)

标签:

原文地址:http://www.cnblogs.com/CtrlCV/p/4981587.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!