前言
已经要开始入手kmp系列的题了
提示:以下是本篇文章正文内容,下面案例可供参考
一、题目
二、算法思想
1.next数组求解
(1)以下标1开始计算
int getNext(char s[],int next[]) {
int len=strlen(s);
// int len=s.lengh();
next[1]=0;
int j=0;
int i=1;
while(i<len) {
if(j==0||s[i]==s[j]) next[++i]=++j;//先i自增后再指向i位,i++; next[i]=++j
// 而next[i++]是先指向i位,再对i自增 next[i]=++j; i++;
else j=next[j]; //回溯到j位之前的前缀位置 然后在进行比较
//为什么回溯到1-j前缀的位置
//因为对于1-i位前缀和后缀是一样的,而对于前缀的前缀(即1-j位的前缀)
//同样也是后缀的前缀,
//前缀的前缀=前缀的后缀
//后缀=前缀
//后缀的前缀=后缀的后缀 = 前缀的前缀=前缀的后缀
//所以前缀(即j位前的前缀next[j])=i位的后缀,
//回溯到s[i]==s[j],此时,j前面的必定对于i前面的有相等的字符
//因为前i项找到了前缀,
//相当于一直缩小前缀的长度,找到符合的一项
}
cout<<"--------------\n";
}
简单步骤:
(2)以下标0开始计算
两者的思路差不多,本题使用的是以0为下标
void getNext(char s[]){
int len=strlen(s);
next[0]=-1;
int i=0;
int j=-1;
while(i<len){
if(j==-1||s[i]==s[j]) next[++i]=++j;
else j=next[j];
}
}
2.思想
以下标0开始计算next数组可以求得整个串的前后缀相等的个数,求得这个个数next[m] (m为s串长度),对于m-next[m]可以相当于是除了最大相等前后缀剩下的串,如果m%(m-next[m])==0,说明这个剩下的串是一个周期,如果是一个周期性的字符串,必然有next[m]含有至少一个周期串,所以只要m%(m-next[m])==0,即可说明s是一个周期串,而个数就是m/(m-next[m]);
三、代码
//思路:长度减去next[len]是除掉主串中最长相等前后缀,剩下的字符串,
//如果长度len是这个剩下的字符串的长度的倍数, 也说明这是个有周期的字符串
//而这个剩下的字符串就是一个周期,那么就知道周期数了
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int next[10000001];
char s[10000001];
void getNext(char s[]){
int len=strlen(s);
next[0]=-1;
int i=0;
int j=-1;
while(i<len){
if(j==-1||s[i]==s[j]) next[++i]=++j;
else j=next[j];
}
}
int main(){
while(~scanf("%s",s)){
if(s[0]=='.')break;
int m=strlen(s);
// cout<<m<<endl;
getNext(s);
if(m%(m-next[m])==0) printf("%d\n",m/(m-next[m]));
else printf("1\n");
}
}