poj2185 Milking Grid

關於如何求一個(不完整)字符串的最小循環節:ide

n - nex[n - 1]便可。spa

若n % 循環節長度 == 0則表示這個字符串可由若干個循環節構成。code

不然最後一個循環節有殘缺。blog

回到本題:字符串

首先行列分開。get

一個直觀的想法是求出最小循環節的lcm,可是諸君請看:io

2 8event

abDQRVabclass

aaaabaaacli

而後怎麼作呢?

有一種作法是枚舉行的長度,而後列用KMP

而後,略加思索,咱們行也能夠用KMP啊......

而後雙KMP搞定。

調了很久是由於把while寫成了if......

 

 1 #include <cstdio>
 2 
 3 const int N = 10010, M = 100;
 4 
 5 char s[N][M];
 6 int nex[N], m, n;
 7 
 8 inline bool equala(int a, int b) {
 9     for(int i = 0; i < m; i++) {
10         if(s[a][i] != s[b][i]) {
11             return 0;
12         }
13     }
14     return 1;
15 }
16 
17 inline bool equalb(int a, int b) {
18     for(int i = 0; i < n; i++) {
19         if(s[i][a] != s[i][b]) {
20             return 0;
21         }
22     }
23     return 1;
24 }
25 
26 inline int geta() {
27     nex[0] = 0;
28     for(int i = 1, j = 0; i < n; i++) {
29         while(j && !equala(i, j)) {
30             j = nex[j - 1];
31         }
32         if(equala(i, j)) {
33             j++;
34         }
35         nex[i] = j;
36     }
37     return n - nex[n - 1];
38 }
39 
40 inline int getb() {
41     nex[0] = 0;
42     for(int i = 1, j = 0; i < m; i++) {
43         while(j && !equalb(i, j)) {
44             j = nex[j - 1];
45         }
46         if(equalb(i, j)) {
47             j++;
48         }
49         nex[i] = j;
50     }
51     return m - nex[m - 1];
52 }
53 
54 int main() {
55     while(scanf("%d%d", &n, &m) != EOF) {
56         for(int i = 0; i < n; i++) {
57             scanf("%s", s[i]);
58         }
59 
60         int c = geta();
61         int d = getb();
62         printf("%d\n", c * d);
63     }
64     return 0;
65 }
AC代碼
相關文章
相關標籤/搜索