您的位置:首页 > 其它

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

2015-08-27 16:10 483 查看
大意:告诉你一个字符矩阵 然后让你找出一个最小的矩阵 整个矩阵能用该小矩阵去填充, 可以超出边界

例如:

ABABABA

ABABABA

可以用AB去铺满

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

分析:

把整个矩阵先按行来看

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

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

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

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

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

void Get(char *s, int *next) {
int l = strlen(s);
int j = 0, k = -1;
next[0] = -1;
while(j < l) {
if(k == -1 || s[j] == s[k]) {
next[++j] = ++k;
} else {
k = next[k];
}
}
}
const int maxn = 10005;
int next[maxn];

int Circle(char *s) {
Get(s, next);
int l = strlen(s);
return l - next[l];
}

char s[maxn][maxn];
char s2[maxn][maxn];
int main() {
int n, m;
while(EOF != scanf("%d %d",&n, &m) ) {
for(int i = 0; i < n; i++) {
scanf("\n%s", s[i]);
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
s2[j][i] = s[i][j];
}
}
int ans = 1;
for(int i = 0; i < n; i++) {
int x = Circle(s[i]);
int y = __gcd(ans, x);
ans = ans * x / y;
}
if(ans > m) ans = m;
int sum = 1;
for(int i = 0; i < ans; i++) {
int x = Circle(s2[i]);
int y = __gcd(sum, x);
sum = sum * x / y;
}
if(sum > n) sum = n;
printf("%d\n", ans * sum);
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: