Codeforces Gym100502H:Clock Pictures(KMP算法)

http://codeforces.com/gym/100502/attachments

题意:有两个时钟上面有n个指针,给出的数字代表指针的角度。问能否在某一时刻使得两个时钟的指针重合。

思路:容易想到先对指针角度排序,然后相邻指针相减得到一个间距。如果这些间距能够相同的话,那么就代表可以在某个时刻重合。

最暴力地做法就是O(n^2)的复杂度。用第一个时钟的每一个间距去匹配第二个时钟的每一个间距,如果发现有能够匹配到的就说明可以。

明明都想到匹配了,但是我以为可以贪心地做,但是一直WA。比赛之后听到是KMP。瞬间爆炸。= =太弱了。

因为是环状的,所以要让第一个时钟的间距向后延伸n-1个。

然后让第一个时钟的间距当文本串,第二个时钟的间距当模式串,然后跑一下KMP就好了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 200010
 4 const int maxdeg = 360000;
 5 int nxt[N], a[N], b[N], c[N+N], d[N], n;
 6 
 7 void make_next() {
 8     for(int i = 0; i <= n; i++) nxt[i] = 1;
 9     int k = 0, j = 1;
10     nxt[1] = 0;
11     while(j <= n) {
12         if(k == 0 || d[k] == d[j]) {
13             k++; j++;
14             nxt[j] = k;
15         } else k = nxt[k];
16     }
17 }
18 
19 bool KMP() {
20     int k = 1, j = 1;
21     make_next();
22     while(j < 2 * n) {
23         if(k == 0 || d[k] == c[j]) {
24             k++; j++;
25             if(k == n) return true;
26         } else k = nxt[k];
27     }
28     return false;
29 }
30 
31 int main() {
32     scanf("%d", &n);
33     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
34     for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
35     sort(a + 1, a + 1 + n);
36     sort(b + 1, b + 1 + n);
37     for(int i = 2; i <= n; i++) {
38         c[i] = a[i] - a[i-1];
39         d[i] = b[i] - b[i-1];
40     }
41     c[1] = a[1] - a[n] + maxdeg;
42     d[1] = b[1] - b[n] + maxdeg;
43     for(int i = n + 1; i < 2 * n; i++)
44         c[i] = c[i-n];
45     if(KMP()) puts("possible");
46     else puts("impossible");
47     return 0;
48 }
原文地址:https://www.cnblogs.com/fightfordream/p/6506760.html