【Ybtoj 第8章例题4】子串拆分【KMP】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

——因为一个数组开小了调了1个小时,我无语了啊啊啊啊啊…TOT

这道题因为数据不大,可以直接跑 n 2 n^2 n2
考虑枚举左端点,设左端点为 l , S = C [ l , ∣ C ∣ ] l,S=C[l,|C|] lS=C[l,C],那么对字符串S跑一次 K M P KMP KMP
然后在统计过程中,假设现在在i位置,则 S [ 1 , j ] = S [ i − j + 1 , i ] S[1,j]=S[i-j+1,i] S[1,j]=S[ij+1,i]。如果 j ∗ 2 > = i j*2>=i j2>=i,那么令j=p[j],此时 A [ 1 , j ] = a [ i − j + 1 , i ] , j A[1,j]=a[i-j+1,i],j A[1,j]=a[ij+1,i]j不断沿指针回跳,直到 j ∗ 2 < i j*2<i j2<i。然后再判断j是否大于等于k,如果是,那么累加答案。


代码

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

char s[20010],c[20010];
int ans,j,k,l,len,m,p[20010];

int main() {
    
    
	scanf("%s",c+1);
	scanf("%d",&k);
	len=strlen(c+1);
	for(register int t=1; t<=len; t++) {
    
    
		memset(s,0,sizeof(s));
		memset(p,0,sizeof(p));
		for(register int w=1;w+t-1<=len;w++)
			s[w]=c[w+t-1]; //处理左端点
		j=0,l=strlen(s+1);
		for(register int i=2; i<=l; i++) {
    
    
			while(j&&s[i]!=s[j+1])
				j=p[j];
			if(s[i]==s[j+1])
				j++;
			p[i]=j;
		}
		j=0;
		for(register int i=1; i<=l; i++) {
    
    
			while(j&&s[i]!=s[j+1])
				j=p[j];
			if(s[i]==s[j+1])
				j++;
			while((j<<1)>=i)j=p[j];
			if(j>=k)ans++;
		}
	}
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/114677810
今日推荐