KMP——求border数组&字符串匹配

KMP——求border数组&字符串匹配

拼接字符串法

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
#define endl '\n'
#define int long long

const int N=2e6+114;

void build_border(string str,vector<int>& border){//数组从0开始计数 
	int str_len=str.length();
	border[0]=0;
	for(int i=1;i<str_len;i++){
		int j=border[i-1];
		while(j>0 && str[j]!=str[i])j=1+border[j-1]-1;//转到第二长的可匹配前缀    
		//-1是因为字符串从0开始,border[j-1]长度-1才是正确的位置 ,+1是因为要暴力扩展是否匹配 
		if(str[j]==str[i])j++;
		border[i]=j;
	}
	return;
}

signed main(){
	IOS
	
	string s1,s2;
	cin>>s1>>s2;
	
	int len2=s2.length();
	string str=s2+"#"+s1;
	int len=str.length();
	
	vector<int>border(len);
	build_border(str,border);
	for(int i=len2*2-1;i<len;i++){
		if(border[i]==len2)cout<<i-2*len2+1<<endl;
	}
	
	vector<int> border2(len2);
	build_border(s2,border2);
	for(int i=0;i<len2;i++){
		cout<<border2[i]<<" ";
	}
	return 0;
}

双指针滑动法

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
#define endl '\n'
#define int long long

const int N=2e6+114;

void build_border(string str,vector<int>& border){//数组从0开始计数 
	int str_len=str.length();
	border[0]=0;
	for(int i=1;i<str_len;i++){
		int j=border[i-1];
		while(j>0 && str[j]!=str[i])j=1+border[j-1]-1;//转到第二长的可匹配前缀    
		//-1是因为字符串从0开始,border[j-1]长度-1才是正确的位置 ,+1是因为要暴力扩展是否匹配 
		if(str[j]==str[i])j++;
		border[i]=j;
	}
	return;
}

signed main(){
	IOS
	
	string s1,s2;
	cin>>s1>>s2;
	
	int len2=s2.length();
	int len1=s1.length();
	vector<int> border2(len2);
	build_border(s2,border2);
	
	int i=0,j=0;
	while(i<len1){
		if(s1[i]==s2[j]){
			i++;
			j++;
			if(j-1==len2-1){
				cout<<i-len2+1<<endl;
				j=border2[j-1]-1+1;
			}
		}
		else{
			if(j>0){
				j=border2[j-1]-1+1;//滑动后再次循环 
			}
			else{
				i++;
			}
		}
	}
	
	for(int i=0;i<len2;i++){
		cout<<border2[i]<<" ";
	}
	return 0;
}
posted @ 2025-11-26 13:53  10mbps_十兆網路  阅读(0)  评论(0)    收藏  举报