字符串题目

KMP

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int N = 1e6+10;
char a[N];//存字符串
int ne[N];//next数组
void get_next(int len)//len字符串长度
{
	int j=-1;
	ne[0]=-1;
	for(int i=0;i<len;)
	{
		//字符串从a[0]开始,所以ne[++i]
		if(j==-1||a[j]==a[i]) ne[++i]=++j;//字符匹配成功,ne[]值置为j+1
		else j=ne[j];//匹配失败,向前推。推到起点后在上一条语句赋值为-1+1=0
	}
}
int main()
{
	while(scanf("%s",a),a[0]!='.')
	{
		int l=strlen(a);
		get_next(l);
		int n=l-ne[l];//循环节长度
		if(l%n==0)
			cout<<l/n<<endl;
		else
			cout<<"1"<<endl;
	}
	//system("pause");
}

NEXT数组

性质1:对于每一个长度len的子串,该子串的最小循环节为len-next[len]
性质2:kmp的next不断向前递归的过程可以保证对于每一个当前前缀,都有一段后缀与之对应

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int N = 1e6+10;
char a[N];//存字符串
int ne[N];//next数组
void get_next(int len)//len字符串长度
{
	int j=-1;
	ne[0]=-1;
	for(int i=0;i<len;)
	{
		//字符串从a[0]开始,所以ne[++i]
		if(j==-1||a[j]==a[i]) ne[++i]=++j;//字符匹配成功,ne[]值置为j+1
		else j=ne[j];//匹配失败,向前推。推到起点后在上一条语句赋值为-1+1=0
	}
}
int main()
{
	while(scanf("%s",a),a[0]!='.')
	{
		int l=strlen(a);
		get_next(l);
		int n=l-ne[l];//循环节长度
		if(l%n==0)
			cout<<l/n<<endl;
		else
			cout<<"1"<<endl;
	}
	//system("pause");
}
posted @ 2022-08-26 14:16  zyc_xianyu  阅读(20)  评论(0编辑  收藏  举报