[Ybtoj Chapter 8 Example 4] Substring splitting [KMP]

Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here


Problem-solving ideas

——Because an array has been reduced and adjusted for 1 hour, I am speechless...TOT

Because the data is not big for this question, you can run n 2 n^2 directlyn2 .
Consider enumerating the left end point, let the left end point bel, S = C [l, ∣ C ∣] l, S=C[l,|C|]lS=C[l,C ] , then runKMP KMPon the string SK M P .
Then in the statistical process, assuming that it is now at position i, thenS [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 , then let j=p[j], at this timeA [1, j] = a [i − j + 1, i], j A[1,j]=a[i-j+1,i], jA[1,j]=a[ij+1,i ] , j keeps jumping back along the pointer untilj ∗ 2 <ij*2<ij2<i . Then judge whether j is greater than or equal to k, and if so, add up the answers.


Code

#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);
}

Guess you like

Origin blog.csdn.net/kejin2019/article/details/114677810