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代码
相关文章
相关标签/搜索