题目链接:http://poj.org/problem?id=2185
题目大意:给定一个n*m的字符矩阵,每行字符会有若干个相同的串组成,最后一个重复串不一定要完整。问这个矩阵可由面积最小为多少的矩阵组成。
解题思路:第一次看完题目,有点不解,又看了下测试数据,觉得没有思路,又重复看了一次题目,注意到一句话:Note that the dimensions of the small rectangular unit do not necessarily need to divide evenly the dimensions of the entire milking grid。在看一遍测试数据就大概理解清楚题意了,就是每行的重复子串长度的最小公倍数,如果超过n,则为n.提交果断地Wa了,后来发现第二行的首字母和第一行的不一样,这样两行不能简单地这样求公倍数得到ans1,所以加了各判断:如果两行不想等,直接输出n*m.提交又Wa。Wa了两次以后发现其实可以几行几行的循环,也是重复子串。所以,针对每列求最短重复子串长度,然后求最小公倍数,求出来的ans2表示矩阵中有ans2行是和后面的重复的,也要判断是否大于m,大的话ans2为m.最后输出ans1*ans2.本题有一定思维难度。
测试数据:
3 5
ABCDE
BCDEF
CDEFG
3 5
ABABA
ABABA
ABABA
4 5
ABABA
BABAB
ABABA
BABAB
4 5
ABABA
BABAA
ABCCA
BAABA
代码:
#include <stdio.h>
#include <string.h>
#define MAX 10010
#define MIN 110
int len,next[MAX];
int row[MAX],col[MIN];
char str[MAX][MIN],rostr[MIN][MAX];
int Kmp(char *str) {
int i,j,k,len;
len = strlen(str);
i = 0,j = -1;
next[i] = -1;
while (i < len) {
if (j == -1 || str[i] == str[j])
i++,j++,next[i] = j;
else j = next[j];
}
return len - next[len];
}
int gcd(int n,int m) {
int r = n % m;
while (r != 0) {
n = m,m = r;
r = n % m;
}
return m;
}
int lcd(int n,int m) {
return n / gcd(n,m) * m;
}
int main()
{
int i,j,k,m,n;
int res,ans,flag;
while (scanf("%d%d",&n,&m) != EOF) {
flag = 0,res = ans = 1;
for (i = 0; i < n; ++i) {
scanf("%s",str[i]);
row[i] = Kmp(str[i]);
}
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
rostr[j][i] = str[i][j];
for (j = 0; j < m; ++j)
col[j] = Kmp(rostr[j]);
for (i = 0; i < m; ++i)
ans = lcd(ans,col[i]);
ans = n < ans ? n : ans;
for (i = 0; i < ans; ++i)
res = lcd(res,row[i]);
res = m < res ? m : res;
printf("%d\n",ans * res);
}
}
本文章为ZeroClock原创,但可以转载,因为我们是兄弟!