题意:求最小的模式块,使其无限扩展后包含给你的矩阵块(看别人题解才懂的题意);
分析:假设存在一个模式块可以满足上述条件,那么必然存在一个起点在(0,0)的模式块满足上述条件;
对于每一行,我们找出所有可以满足条件的前缀记录下长度,那么满足所有行的最短的长度就是该模式块的宽r;
对于模式块的长,我们把宽r的字符串压缩看出一个字符,然后再进行KMP,找出该字符串的最小循环串,即长l;
答案就是r * l;
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>
#define INF 0x3f3f3f3f
#define IMAX 2147483646
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int
using namespace std;
int r, c;
char mp[11111][99];
int cnt[99],nn[11111];
int main() {
scanf("%d%d", &r, &c);
for (int i = 1; i <= r; i++)
scanf("%s", mp[i] + 1);
for (int i = 1; i <= r; i++) {
nn[1] = 0;
for (int j = 2, k = 0; j <= c; j++) {
while (k > 0 && mp[i][k + 1] != mp[i][j])
k = nn[k];
if (mp[i][k + 1] == mp[i][j])k++;
nn[j] = k;
}
int tt = c;
while (tt != 0) {
cnt[c - nn[tt]]++;
tt = nn[tt];
}
}
int a;
for(int i = 1;i <= c;i++)
if (cnt[i] == r) {
a = i;
break;
}
nn[1] = 0;
for (int i = 2, j = 0; i <= r; i++) {
while (j > 0 && strcmp(mp[i] + 1, mp[j + 1] + 1) != 0)
j = nn[j];
if (strcmp(mp[i] + 1, mp[j + 1] + 1) == 0)j++;
nn[i] = j;
}
printf("%d\n", (r - nn[r])*a);
return 0;
}