KMP(烤馍片)算法想必大家都会吧,这次让我们来做一道题——求最小循环节。
先上题,题目大意是这样的(我对原题进行了一些改动):给你一个字符串s(|s|≤1,000,000),求其最小循环节。最小循环节指有一s的子串a,s=aaa...a,也就是共n个a可顺序拼成原串s(原题是说s=a^n)。
样例:
1.abcd 最小循环节为其本身
2.aaaa 最小循环节为a
3.ababab 最小循环节为ab
很多大佬会说:这不是弱智题吗?那你就错了,请看我慢慢道来。
首先看到这道题,第一反应应该就是哈希(划掉)KMP,我们对它进行一个变形。
从哪里入手呢?想想next数组?
首先,我们看看next数组的定义
next[i]=max{k<i|s[1..k]=s[i-k+1..i]}
通俗地讲,next[i]表示s的前i个字符构成的子串t中t的前缀与后缀相等的最长长度。
这个大家都懂的吧,如果还不知道KMP,那么先学学吧。
看了这个,大家是否有什么感觉了呢?next...相等...前缀与后缀...循环节!只有前缀与后缀相等,这个前缀(或后缀)才有可能是循环节!
不错,其实我们根本就不用考虑KMP的匹配,用next数组就可以求出答案。
讲到这里,一般的解题博客就开始贴代码了,emmm...要不我也贴个代码?
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
char s[1000001];
int Next[1000001],lens,nextN;
void getNext(){
int k=0;
Next[1]=0;
for(int i=2;i<=lens;i++){
while(k&&s[k+1]!=s[i]) k=Next[k];
if(s[k+1]==s[i]) k++;
Ne