poj2185 Milking Grid(二维KMP+最小覆盖矩阵)

题意:在字符矩阵中找出一个最小子矩阵,使其多次复制所得的矩阵包含原矩阵。首先我们计算答案矩阵的列数,叫做宽。对每行都计算出所有的重复子串可能的长度,如:AAAABAAA,可能的重复子串长度为:5,6,7,8.如何计算呢?k从m开始,每次k-fail[k]即为重复子串长度,k=fail[k],直到k=0.每行中都出现过的最小长度即为答案矩阵的宽。(遇到一个可能长度就计数器+1,最后从小到大扫一遍,次数为n的即可)。然后我们要计算答案矩阵的行数。那么就把每一行长度为答案矩阵的宽的前缀取出来作为一个单位,进行二维kmp(每次比较一个字符串。)其实和一维一模一样hh。。然后这样的最小重复子串长度就是答案矩阵的行数。


#include <cstdio>
#include <cstring>
#define N 10010
int n,m,fail[N],f[80];
char s[N][80];
inline void getfail(char *t){
	int k=0;fail[1]=0;
	for(int i=2;i<=m;++i){
		while(k&&t[k+1]!=t[i]) k=fail[k];
		if(t[k+1]==t[i]) ++k;
		fail[i]=k;
	}
}
int main(){
//	freopen("a.in","r",stdin);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) scanf("%s",s[i]+1);
	for(int i=1;i<=n;++i){
		getfail(s[i]);
		for(int k=m;k;k=fail[k]) f[m-fail[k]]++;
	}
	for(int i=1;i<=m;++i) if(f[i]==n) m=i;
	for(int i=1;i<=n;++i) s[i][m+1]=0;
	int k=0;fail[1]=0;
	for(int i=2;i<=n;++i){
		while(k&&strcmp(s[k+1]+1,s[i]+1)) k=fail[k];
		if(strcmp(s[k+1]+1,s[i]+1)==0) ++k;
		fail[i]=k;
	}
	printf("%d\n",m*(n-fail[n]));
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值