最大跨距

本文深入探讨了KMP算法的原理与应用,通过具体案例展示了如何使用KMP算法进行字符串匹配,包括Next数组的计算和匹配过程的优化,特别强调了在匹配失败时如何快速定位,以达到减少重复比较的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解:

KMP即可。先用第一个串从头开始匹配,再反转标准串和第二个串,再匹配一次,然后用两个位置处理出答案,细节就是该怎么减和-1的判断。注意读入用getchar,我用gets要1000ms+,用getchar直接0ms。

简谈一下KMP,先处理出短串的Next数组,即最长相同前后缀长度,方便我们匹配失败后直接跳到下一个相同开头的地方。

然后再用类似的方法匹配标准串,利用Next数组可以在匹配失败的时候直接跳到下一个符合条件的地方,大幅缩短匹配时间。

时间复杂度O(0)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define MAXA 100005
using namespace std;
char Std[MAXA],S1[MAXA],S2[MAXA],Temp;
int StdLen,Len1,Len2,pos,Next[MAXA],k,Left = -1,Right = -1;
bool Flag;
int main() {
//	freopen("dis.in","r",stdin);
//	freopen("dis.out","w",stdout);
	while((Temp = getchar()) && Temp != ',')
	   Std[StdLen++] = Temp;
	while((Temp = getchar()) && Temp != ',')
	   S1[Len1++] = Temp;
	while((Temp = getchar()) && Temp != '\n')
	   S2[Len2++] = Temp;
	
	if(Len1 + Len2 > StdLen) {
		printf("-1");
		return 0;
	}
	Next[0] = k = -1;
	for(int i=1;i<Len1;i++) {
		while(k > -1 && S1[k + 1] != S1[i])
		      k = Next[k];
		if(S1[k + 1] == S1[i])
		   k++;
		Next[i] = k;
	} 
	k = -1;
	for(int i=0;i<StdLen;i++) {
		while(k > -1 && Std[i] != S1[k + 1])
		   k = Next[k];
		if(S1[k + 1] == Std[i])
		   k++;
		if(k == Len1 - 1) {
			Left = i - Len1 + 1;
			break;
		}
	}
	reverse(Std,Std + StdLen);
	reverse(S2,S2 + Len2);
	memset(Next,0,sizeof(Next));
	Next[0] = k = -1;
	for(int i=1;i<Len2;i++) {
		while(k > -1 && S2[k + 1] != S2[i])
		      k = Next[k];
		if(S2[k + 1] == S2[i])
		   k++;
		Next[i] = k;
	} 
	k = -1;
	for(int i=0;i<StdLen;i++) {
		while(k > -1 && Std[i] != S2[k + 1])
		   k = Next[k];
		if(S2[k + 1] == Std[i])
		   k++;
		if(k == Len2 - 1) {
			Right = i - Len2 + 1;
			break;
		}
	}
	//cout << Left << " " << Right << endl;
	if(Left == -1|| Right == -1 || Left + Len1 - 1 + Len2 + Right > StdLen) {
		printf("-1");
		return 0;
	}
	printf("%d",StdLen - (Left + Len1) - (Right + Len2) );
}
/*
abcd123ab888efghij45ef67kl,ab,ef
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值