POJ 2185 Milking Grid

题目大意:

        每天早上FJ挤奶的牛都会排成一个矩阵,R行C列(1 ≤ R ≤ 10,000,1 ≤ C ≤ 75),FJ在喂奶过程中给牛的行为进行了分类,给不同的牛贴不同的分类标签,标签为一大写字母,然后FJ神奇地发现这个大矩阵是由某个小矩阵重复排列而得的,但是这个大矩阵又不需要严格地均匀分成若干小矩阵(当然也可以)。

        现只有一个测例,测例中给出R、C以及由大写字母组成的矩阵,隔行但是没行中没有空格等间隔,要求输出最小循环矩阵的面积。

题目链接

注释代码:

/*   
 * Problem ID : POJ 2185 Milking Grid
 * Author     : Lirx.t.Una   
 * Language   : G++  
 * Run Time   : 16 ms   
 * Run Memory : 1168 KB   
*/ 

#pragma G++ optimize("O2")

#include <string.h>
#include <stdio.h>

//对于最小循环矩阵的求法
//可以将每一行看做一个字符,对行组成的字符串求最小循环节的长度
//并将每一列也看做一个字符,对每列组成的字符串求最小循环节的长度
//最终最小循环矩阵的面积就是以上两个值相乘的结果
//比较的时候用字符串比较函数来模拟两个字符的等值判断

//对于一列组成的字符串之间的等值判断需要自己写函数来模拟strcmp!!

#define	TRUE		1
#define	FALSE		0

//maximum row length
#define	MAXR		10002
//maximum column length
#define	MAXC		77

typedef	int		BOOL;

char	g[MAXR][MAXC];//grid,网格,存放字符矩阵
int		nxt[MAXR];//next数组

int		r, c;//行长和列长

BOOL
eq( int x, int y ) {//equal
	//比较两个列所表示的字符串
	//x、y分别表示比较列的列序号
	
	int		i;
	
	for ( i = 1; i <= r; i++ )
		if ( g[i][x] != g[i][y] )
			return FALSE;
		
		return TRUE;
}

int
rkmp(void) {//row_KMP,对行进行kmp操作
	
	int		i, j;
	
	for ( nxt[1] = 0, j = 0, i = 2; i <= r; i++ ) {
		
		while ( j > 0 && strcmp(g[j + 1] + 1, g[i] + 1) )
			j = nxt[j];
		
		if ( !strcmp(g[j + 1] + 1, g[i] + 1) )
			j++;
		
		nxt[i] = j;
	}
	
	return r - nxt[r];//求得行字符串最小循环节长度
}

int
ckmp(void) {//column_KMP,列进行KMP操作
	
	int		i, j;
	
	for ( nxt[1] = 0, j = 0, i = 2; i <= c; i++ ) {
		
		while ( j > 0 && !eq( j + 1, i ) )
			j = nxt[j];
		
		if ( eq( j + 1, i ) )
			j++;
		
		nxt[i] = j;
	}
	
	return c - nxt[c];//求得列字符串最小循环节长度
}

int
main() {
	
	int		i, j;
	
	scanf("%d%d", &r, &c);
	
	for ( i = 1; i <= r; i++ )
		scanf("%s", g[i] + 1);
	
	printf("%d\n", rkmp() * ckmp());
	
	return 0;
}

无注释代码:

#include <string.h>
#include <stdio.h>

#define	MAXR	10000
#define	MAXC	75

char	g[MAXR][MAXC + 1];
short	prv[MAXR];
int		r, c;

int
c_eq( int x, int y ) {

	int		i;

	for ( i = 0; i < r; i++ )
		if ( g[i][x] != g[i][y] )
			return 0;

	return 1;
}

int
build_r(int	r) {

	int		i, j;

	prv[0] = -1;
	for ( j = -1, i = 1; i < r; i++ ) {
	
		while ( j > -1 && strcmp(g[j + 1], g[i]) ) j = prv[j];
		if ( !strcmp(g[j + 1], g[i]) ) j++;

		prv[i] = j;
	}

	return r - 1 - prv[r - 1];
}

int
build_c(int c) {

	int		i, j;

	prv[0] = -1;
	for ( j = -1, i = 1; i < c; i++ ) {
	
		while ( j > -1 && !c_eq( j + 1, i ) ) j = prv[j];
		if ( c_eq( j + 1, i ) ) j++;

		prv[i] = j;
	}

	return c - 1 - prv[c - 1];
}

int
main() {
	
	int		i;

	scanf("%d%d", &r, &c);
	for ( i = 0; i < r; i++ ) scanf("%s", g[i]);
	printf("%d\n", build_r(r) * build_c(c));

	return 0;
}
单词解释:

milk:vt, 挤奶

grid:n, 网格,格子

column:n, 一列,列

feeding:n, 饲养

lable:vt, 标注,贴标签于

breed:n, (生物)品种,种类

repetitively:adv, 重复地

tile:vt, 铺瓦片

evenly:adj, 平均地,均匀地

intervening:adj, 介于中间的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值