POJ 1961 Period

题目链接

Period

知识点

KMP算法,最小循环节问题

实现

码前思考

  1. 典型地利用KMP算法中的nex数组求解循环节的问题,之前做过一道相似的题目;
  2. 对于求循环节的问题,主要就是在原始的getNex操作之后加入一些操作就好,实质还是利用nex数组,可见其重要性;
  3. 理解nex[i]的含义,其含义是子串s[0...i]的最长匹配前缀;
  4. 这道题目不允许输出K==1的情况,因此需要在循环节的基础代码上,再增加一些限制;
    5.循环节的思路:
    ① 得到理想中的最小循环节长度mod = (len-1) - next[len-1],例如对于ababa的理想mod = 4 - 2 = 2;
    ② 使用len%mod进行判断,如果len%mod==0,那么最小循环节长度就是mod,否则最小循环节长度就是len,舍去。
    ③由于此题的特殊性,因此要在len%mod==0之后还要继续判断最小循环节长度是否是len,是的话得舍去。例如abc,它的每个循环节都是当前len得舍去!

代码实现

//使用KMP求解循环节的问题
//需要掌握循环节的公式 
#include <cstdio>
#include <cstring>
const int maxn = 1e6+10;

char p[maxn];
int nex[maxn];

int n;

void getNex(){
	int len = strlen(p);
	nex[0] = -1;
	int j = -1;
	for(int i=1;i<len;i++){
		while(j!=-1&&p[i]!=p[j+1]){
			j=nex[j];
		}
		if(p[i]==p[j+1]){
			j++;
		}
		nex[i] = j;
		//下面是判断循环节
		int mod = i - nex[i];
		if(nex[i]!=-1 && (i+1)%mod == 0){
			printf("%d %d\n",i+1,(i+1)/mod);

		} 
	} 
} 

int main(){
	int cnt=0;
	while(scanf("%d",&n) && n!=0){
		scanf("%s",p);
		printf("Test case #%d\n",++cnt);
		getNex();
		printf("\n");
	}
	return 0;
}
 

码后反思

  1. 还是要特别掌握KMP中nex数组的含义;
  2. 一定要背下循环节的计算思路!!!同时要加以一定的理解,直到那两步操作的结果是什么~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值