poj2185Milking Grid【kmp next数组求循环节】

大意:告诉你一个字符矩阵   然后让你找出一个最小的矩阵  整个矩阵能用该小矩阵去填充,  可以超出边界

例如:

ABABABA

ABABABA

可以用AB去铺满

最后一列A用AB填充 超出边界部分就忽略

分析:

把整个矩阵先按行来看

求出每行字符串的最小循环节 也就是l - next[l]

然后求出他们的最小公倍数  也就是公共的最小循环节   注意要把该倍数与边界作比较  取小值

通过以上 就能求出  用n行用最小公倍数列做区间能把后面几列铺完

用同样的方法对1~最小公倍数列进行求解

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 void Get(char *s, int *next) {
 9     int l = strlen(s);
10     int j = 0, k = -1;
11     next[0] = -1;
12     while(j < l) {
13         if(k == -1 || s[j] == s[k]) {
14             next[++j] = ++k;
15         } else {
16             k = next[k];
17         }
18     }
19 }
20 const int maxn = 10005;
21 int next[maxn];
22 
23 int Circle(char *s) {
24     Get(s, next);
25     int l = strlen(s);
26     return l - next[l];
27 }
28 
29 char s[maxn][maxn];
30 char s2[maxn][maxn];
31 int main() {
32     int n, m;
33     while(EOF != scanf("%d %d",&n, &m) ) {
34         for(int i = 0; i < n; i++) {
35             scanf("
%s", s[i]);
36         }
37         for(int i = 0; i < n; i++) {
38             for(int j = 0; j < m; j++) {
39                 s2[j][i] = s[i][j];
40             }
41         }
42         int ans = 1;
43         for(int i = 0; i < n; i++) {
44             int x = Circle(s[i]);
45             int y = __gcd(ans, x);
46             ans = ans * x / y;
47         }
48         if(ans > m) ans = m;
49         int sum = 1;
50         for(int i = 0; i < ans; i++) {
51             int x = Circle(s2[i]);
52             int y = __gcd(sum, x);
53             sum = sum * x / y;
54         }
55         if(sum > n) sum = n;
56         printf("%d
", ans * sum);
57     }
58 }
View Code
原文地址:https://www.cnblogs.com/zhanzhao/p/4763639.html