KMP字符串匹配算法

 
KMP算法的要点是避免回溯和Next[]数组,其中,Next[]数组中存的是最长公共前后缀的长度.
 
1.KMP模板

例题:HDU2087剪花布条

 

int Next[N],cnt;
//构建Next[]数组 void getNext(char *p,int plen){ Next[1]=Next[0]=0; for(int i=1;i<plen;i++){ int j=Next[i]; while(j&p[i]!=p[j])j=Next[i]; if(p[i]==p[j])Next[i+1]=j+1; else Next[i+1]=0; } }
//KMP算法 void kmp(char *s,char *p){ int last=-1,slen=strlen(s),plen=strlen(p); getNext(p,plen); int j=0; for(int i=0;i<slen;i++){ while(j&&s[i]!=p[j])j=Next[j]; if(s[i]==p[j])j++; if(j==plen){ if(i-last>=plen){ cnt++; last=i; } } } }

  

2.DP+KMP

例题:HDU3336

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9,MOD = 1e4+7;
int dp[N],nex[N];
char s[N];
int len1,len2;
void getnext(){
    int i=0,j=-1;
    nex[i]=j;
    while(i<len1){
        if(j==-1||s[i]==s[j])nex[++i]=++j;
        else j=nex[j];
    }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int sum=0;
        scanf("%d",&len1);
        scanf("%s",&s);
        memset(dp,0,sizeof(dp));
        getnext(); 
        for(int i=1;i<=len1;i++){
            dp[i]=dp[nex[i]]+1;
            sum=(sum+dp[i])%MOD;
        }
        printf("%d\n",sum);
    }
    return 0;
}

  

3.矩阵快速幂+KMP

例题:洛谷P3193

#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
const int N = 5e3+255;
int f[N][30],n,m,k,nxt[N],match[N][50];
char md[N];
void kmp(){
	nxt[0]=-1;
	for(int i=1;i<=m;i++){
		int j=nxt[i-1];
		while(j!=-1&&md[j+1]!=md[i])j=nxt[j];
		nxt[i]=++j;
	}
	nxt[0]=0;
	for(int i=0;i<m;i++){
		for(int j='0';j<='9';j++){
			int t=i;
			while(md[t+1]!=j&&t>0)t=nxt[t];
			if(md[t+1]==j)t++;
			if(t<m)match[i][t]++;
		}
	}
}
class matrix{
	public:
		int mr[25][25];
		matrix(){
			memset(mr,0,sizeof(mr));
		}
		matrix operator *(matrix b){
			matrix ans;
			memset(ans.mr,0,sizeof(ans.mr));
			for(int i=0;i<m;i++){
				for(int j=0;j<m;j++){
					for(int p=0;p<m;p++){
						ans.mr[i][j]+=mr[i][p]*b.mr[p][j];
						ans.mr[i][j]%=k;
					}
				}
			}
			return ans;
		}
}F,G;
matrix quickPow(matrix A,int pows){
	matrix ans;
	for(int i=0;i<=m;i++)ans.mr[i][i]=1;
	while(pows){
		if(pows&1)ans=ans*A;
		pows>>=1;
		A=A*A;
	}
	return ans;
}
int main(){
	cin>>n>>m>>k;
	scanf("%s",md+1);
	kmp();
	F.mr[0][0]=1;
	for(int i=0;i<=m;i++){
		for(int j=0;j<=m;j++){
			G.mr[i][j]=match[i][j];
		}
	}
	G=quickPow(G,n);
	F=F*G;
	long long ans=0;
	for(int i=0;i<m;i++){
		ans+=F.mr[0][i];
		ans%=k;
	}
	cout<<ans;
	return 0;
}

  

 

posted @ 2023-03-25 21:21  天雷小兔  阅读(28)  评论(0)    收藏  举报