KMP

Algorithm Desciption

KMP算法是一个用于解决A串是否是B串的子串的问题。这个算法的核心在于当出现不匹配的状态的时候,并不是直接跳回到0的位置上面去,而是去寻找这个已匹配的串中,前缀和后缀相等的长度。(当然如果前缀和后缀不相等,还是0)
用图来解释比如说现在失配了(1,2,3,4这四个段完全相同)

然后就这么跳

图画的丑,不要在意

而怎么跳呢,就需要自己去处理出一个Nxt数组了

Description

给定若干长度小于等于1000000的字符串,询问每个字符串最多由多少个相同的子串重复连接而成(循环节),例如ababab,最多由3个ab连接而成

Input

若干行,每行一个字符串。最后一行是一个"."点号,作为输入的结尾

Output

对应输入的每行,计算最多有多少个相同子串连接而成

Sample Input

abcd 
aaaa 
ababab 
.

Sample Output

1 
4 
3

Analysis

这一道题直接来看的话好像和KMP算法没有什么关系,但是通过KMP算法确实是可以做这一道题的。

对于输入的字符串,它的Nxt值有两种结果

1.最后一个数的前缀长度加上后缀长度大于他自己的长度。这意味着它最长的相同的前缀后缀之间有重叠的地方,如图

这样的话,就容易得出答案为\(t\div(t-Nxt[t-1])\)(t是字符串的长度)

2.如果说没有重合,那么就直接是1就好了

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000002

using namespace std;

char c[maxn];
int k[maxn];

void init();

int main(){
	scanf("%s",c);
	while(c[0]!='.'){
		init();
		int t=strlen(c);
		if(!(t%(t-k[t-1])))printf("%d\n",t/(t-k[t-1]));
		else printf("1\n");
		scanf("%s",c);
	}
}

void init(){
	int t=strlen(c);
	k[0]=0;
	for(int i=1,j=0;i<t;i++){
		while(j>0&&c[i]!=c[j])j=k[j-1];
		if(c[i]==c[j])j++;
		k[i]=j;
	}
}

posted @ 2019-03-17 15:35  Perisino  阅读(187)  评论(2编辑  收藏  举报