USACO 5.1 Musical Themes(KMP,二分 / 暴力)

2015-03-29 21:52:30

思路:这题... 一开始用KMP暴力超时掉了... 套了个二分就过了。。 看比人貌似用暴力也可以过?。

  二分枚举长度,可以证明若重复的theme长度L可行,那么l < L的也可行,符合单调性。

  根据枚举的长度来枚举起点然后KMP即可。

 1 /*
 2 ID:naturec1
 3 PROG: theme
 4 LANG: C++
 5 */
 6 #include <cstdio>
 7 #include <cstring>
 8 #include <cstdlib>
 9 #include <cmath>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <stack>
14 #include <queue>
15 #include <string>
16 #include <iostream>
17 #include <algorithm>
18 using namespace std;
19 
20 #define MEM(a,b) memset(a,b,sizeof(a))
21 #define REP(i,n) for(int i=0;i<(n);++i)
22 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
23 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
24 #define MP(a,b) make_pair(a,b)
25 
26 typedef long long ll;
27 typedef pair<int,int> pii;
28 const int INF = (1 << 30) - 1;
29 
30 int N;
31 int v[5010],dif[5010];
32 int P[5010];
33 
34 void Getnext(int len,int st){
35     P[0] = -1;
36     int j = -1; //当前匹配到的前缀
37     for(int i = 1; i < len; ++i){
38         while(j >= 0 && dif[st + j + 1] != dif[st + i]) j = P[j];
39         if(dif[st + j + 1] == dif[st + i]) j++;
40         P[i] = j;
41     }
42 }
43 
44 int main(){
45     freopen("theme.in","r",stdin);
46     freopen("theme.out","w",stdout);
47     scanf("%d",&N);
48     REP(i,N) scanf("%d",v + i);
49     REP(i,N - 1) dif[i] = v[i + 1] - v[i];
50     N--;
51     int ans = 0;
52     int l = 0,r = N / 2;
53     while(l <= r){
54         int len = getmid(l,r);
55         int res = 0;
56         for(int st = 0; !res && st <= N - 2 * len; ++st){
57             Getnext(len,st);
58             int j = -1;
59              bool flag = false;
60             for(int i = st + len + 1; i < N; ++i){
61                 while(j >= 0 && dif[st + j + 1] != dif[i]) j = P[j];
62                 if(dif[st + j + 1] == dif[i]) j++;
63                 if(j == len - 1){
64                     flag = true;
65                     break;
66                 }
67             }
68             if(flag) res = len;
69         }
70         if(!res) r = len - 1;
71         else l = len + 1,ans = len;
72         //printf("len : %d , l,r : (%d,%d)\n",len,l,r);
73     }
74     if(ans + 1 < 5) printf("0\n");
75     else printf("%d\n",ans + 1);
76     return 0;
77 }

 

posted @ 2015-03-29 21:56  Naturain  阅读(172)  评论(0编辑  收藏  举报