奶牛矩阵 降维处理,hash,kmp

AcWing159. 奶牛矩阵

每天早上,农夫约翰的奶牛们被挤奶的时候,都会站成一个 R 行 C 列的方阵。

现在在每个奶牛的身上标注表示其品种的大写字母,则所有奶牛共同构成了一个 R 行 C 列的字符矩阵。

现在给定由所有奶牛构成的矩阵,求它的最小覆盖子矩阵的面积是多少。

如果一个子矩阵无限复制扩张之后得到的矩阵能包含原来的矩阵,则称该子矩阵为覆盖子矩阵。

输入格式

第 1 行:输入两个用空格隔开的整数,R 和C。

第 2..R+1 行:描绘由奶牛构成的 R 行 C 列的矩阵,每行 C 个字符,字符之间没有空格。

输出格式

输出最小覆盖子矩阵的面积。(每个字符的面积为 1)

数据范围

1≤R≤10000,
1≤C≤75

输入样例:

2 5
ABABA
ABABA

输出样例:

2

提示

样例中给出的矩阵的最小覆盖子矩阵为 AB,面积为 2。

思路:行列独立,采用降维处理,那么可以把r行压缩成一行,组成一维,再用字符串hash,再求出最小循环节ans1=n-ne[n] 
同样也可以对列这样处理,求出ans2,这样求出的两个子矩阵长度的乘积ans1*ans2就是答案。
 

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define M 13331//常用131,13331 
#define N 15000
char s[N][100];
int ne[N];
ull f[N],p[N];
int kmp(int n){//kmp算法 
	for(int i=2,j=0;i<=n;i++){
		while(j>0&&f[i]!=f[j+1]) j=ne[j];
		if(f[i]==f[j+1]) j++;
		ne[i]=j;
	}
	return n-ne[n];//最循环节长度=字符串长度n-next[字符串长度n]
int main(){
	int r,c,ans=0;
	p[0]=1;
	for(int i=1;i<=N;i++)  p[i]=p[i-1]*M;
	scanf("%d%d",&r,&c);
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			cin>>s[i][j];
		}
	}
    //压缩列
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			f[i]=f[i]*M+s[i][j];
		}
	}
	ans=kmp(r);
	memset(f,0,sizeof(f));//记住清0
    //压缩行
	for(int i=1;i<=c;i++){
		for(int j=1;j<=r;j++){
			f[i]=f[i]*M+s[j][i];
		}
	}
	ans*=kmp(c);
	printf("%d",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值