KMP-(HDU1358)Period[前缀中的周期]

本文介绍了如何利用KMP算法解决HDU1358问题,探讨了通过Next数组确定字符串循环节的方法。当满足条件i % (i - Next[i]) == 0 && Next[i] != 0时,可以找到当前循环节,其长度为i - Next[i],循环次数为i / (i - Next[i])。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • KMP-(HDU1358)Period


给个传送门复习下KMP:串的模式匹配算法-KMP算法

  • 思路:

给定Next[i],Next[i]指向的总是上一循环节后面的一个字符所以上一循环节末尾为Next[i]-1

当前循环节的末尾为i-1,易得当前循环节长度:(i-1)-(Next[i]-1)=i-Next[i]

由题意已经假设0~i-1的串是循环的,所以要判断循环是否成立,只要满足长度 i 是当前循环节长度的倍数

即:i%(Next[i]-1)==0同时必须在Next[i]!=0 前提下(不重复的串Next数组中很多0)

 

  • 总结:

 对于Next数组,满足  i % ( i - Next[i] ) == 0 && Next[i] != 0 说明找到当前循环节

循环节长度:i-Next[i]

循环次数:i/(i-Next[i])

  • 代码:

#include<iostream>	
#include<cstring>	
using namespace std;
//HDU1358  Period
#define MAXSIZE 1000005
int Next[MAXSIZE];
char Str[MAXSIZE];
int Len;

void KMP()
{
	int j = -1, k = 0;
	Next[0] = -1;
	while (k < Len)
	{
		if (j == -1 || Str[j] == Str[k])
		{
			j++;
			k++;
			Next[k] = j;    //j==Next[k]
			if (k % (k - j) == 0 && j != 0)
			{
				cout << k << " " << k / (k - j) << endl;
			}
		}
		else
			j = Next[j];
	}
}

int main()
{
	int Case = 0;
	while (cin >> Len && Len)
	{

		cin >> Str;
		cout << "Test case #" << ++Case << endl;
		KMP();
		cout << endl;
	}
	return 0;
}
  • 参考:

Jack Ge for ACM-        KMP算法 —— next 数组的应用 --- 前缀中最小循环节,最大重复次数

他山之石,我之师,共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值