好位置 (kmp)(确定主串是不是模式串的循环串)(2021-08-16)

好位置

题目
给出两个串s和x,定义s中的某一位i为好的位置,当且仅当存在s的子序列请添加图片描述
满足y=x且存在j使得i=kj成立。
问s中是否所有的位置都是好的位置。

输入
一行两个字符串s,x,这两个串均由小写字母构成。
1 <= |s|, |x| <= 200000

输出
Yes表示是。
No表示不是。

示例1
输入
abab
ab
输出
Yes
示例2
输入
abacaba
aba
输出
No
示例3
输入
abc
ba
输出
No

转载于:原版点击Here

(1)首先,说说这个题吧,看起来短小简单,然而根本看不懂
(2)(查的)题意:x是不是s的循环子串
(3)字符串匹配问题:首先,kmp
(4)因为要循环,所以有几个细节:
1.在kmp函数里,之前是找到即返回,现在当找到了,要标记主串匹配成功的末尾flag[i-1]=1,同时,把用于模式串的下标回溯,便于后续匹配j=next[j]
2.在main函数里,从后往前扫描主串,如果是循环模式串,则只有在循环节处,flag[l]=1,其余处,flag[i]=0。l为跳转到完成当前匹配字符串的前一个位置

#include<iostream>
#include<string.h>
using namespace std;
const int maxn=2e5+5;
int Next[maxn];
int flag[maxn];
void prefix(string t){
	int j,k;
	j=0,k=-1;
	Next[0]=-1;
	int len=t.length();
	while(j<len){
		if(k==-1||t[k]==t[j]){
			j++;
			k++;
			Next[j]=k;
		}
		else{
			k=Next[k];
		}
	} 
}
void kmp(string s,string t){
	int i=0,j=0;
	int lens=s.length();
	int lent=t.length();
	while(i<lens){
		if(j==-1||s[i]==t[j]){
			i++;
			j++;
		}
		else{
			j=Next[j];
		}
		if(j==lent){//匹配成功
			flag[i-1]=1;//对于匹配成功的进行末尾标记 
			j=Next[j];//j:回溯的位置 ,方便下次处理 
		}
	}
}
int main(){
	string s,t;
	cin>>s>>t;
	prefix(t);
	memset(flag,0,sizeof(flag));
	kmp(s,t);
	int n=s.length();
	int m=t.length();
	int l=n;
	int ok=1;
	for(int i=n-1;i>=0;i--){
		if(flag[i]){
			l=i-m;//完成此次匹配前的一个位置 
		}
		if(flag[i]==0&&l>=i){//其实l==i也可以
			ok=0;//正常匹配情况下,当i>l时flag=0,flag[l]=1 
			break;
		}
	}
	if(ok)
		cout<<"Yes"<<endl;
	else
		cout<<"No"<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值