C++ | KMP算法模板

next数组初始化

char a[1000006];//原串
char p[1000006];//子串
int pmt[1000006];

void getNext(int m){
	int j=0;
	pmt[0]=0;
	for(int i=1;i<m;++i){
		while(j>0 && p[i]!=p[j])
			j=pmt[j-1];
		if(p[i]==p[j])
			++j;
		pmt[i]=j;
	}
}

以下实例基于上述getNext函数及数据结构执行:

实例1:寻找并输出匹配位置

下例代码中,n为原串a长度,m为子串p长度。以原串第一个字母为下标‘0’位置。

void kmp_findstr(int n,int m){
	getNext(m);
	for(int i=0,j=0;i<n;i++){
		while(j && a[i]!=p[j])
			j=pmt[j-1];
		if(a[i]==p[j])
			++j;
		if(j==m){
			cout<<i-j+1<<endl;
			j=pmt[j-1];
		}
	}
}

实例2:寻找第一次匹配位置

函数返回原串第一次匹配子串的位置,如果不匹配则返回-1。

int kmp_findfirst(int n,int m){
	int place=-1;
	getNext(m);
	for(int i=0,j=0;i<n;++i){
		while(j>0 && p[j]!=a[i])
			j=pmt[j-1];
		if(p[j]==a[i])
			++j;
		if(j==m){
			place=i-m+1;
			break;
		}
	}
	return place;
}

实例3:计算匹配次数

int kmp_strcount(int n,int m){
	int i,j=0,res=0;
	getNext(m);
	for(i=0;i<n;++i){
		while(j>0 && p[j]!=a[i])
			j=pmt[j-1];
		if(p[j]==a[i])
			++j;
		if(j==m)
			++res;
	}
	return res;
}


PS: 力扣周赛最后一题用到KMP了,直接AC。
顺便附上源代码:

class Solution {
private:
	char num[1000006];
	char p[1000006];
	int kmp_next[1000006];
	void getNext(int m){
		int j=0;
		kmp_next[0]=0;
		for(int i=1;i<m;++i){
			while(j>0 && p[i]!=p[j])
				j=kmp_next[j-1];
			if(p[i]==p[j])
				++j;
			kmp_next[i]=j;
		}
	}
	int kmp(int n,int m){
		int i,j=0,res=0;
		getNext(m);
		for(i=0; i<n; ++i){
			while(j>0 && p[j]!=num[i])
				j=kmp_next[j-1];
			if(p[j]==num[i])
				++j;
			if(j==m)
				++res;
		}
		return res;
	}
public:
    int countMatchingSubarrays(vector<int>& nums, vector<int>& pattern) {
    	int n=nums.size(),m=pattern.size();
        for(int i=0;i<n-1;i+=1){
        	if(nums[i+1]>nums[i])
        		num[i]='a';
        	else if(nums[i+1]==nums[i])
        		num[i]='b';
        	else if(nums[i+1]<nums[i])
        		num[i]='c';
		}
		num[n-1]='d';
		for(int i=0;i<m;i+=1){
			if(pattern[i]==1)
				p[i]='a';
			else if(pattern[i]==0)
				p[i]='b';
			else if(pattern[i]==-1)
				p[i]='c';
		}
		int res=kmp(n,m);
		return res;
    }
};

你可能感兴趣的:(C/C++,算法,c++)