1. 程式人生 > >KMP演算法C++實現

KMP演算法C++實現

 KMP演算法在資料結構(C語言版)裡算是比較難的地方了,難就難在next陣列的求法,但偏偏很多資料在這一點都比較含糊,下面是我學完KMP的一些思考和程式碼。

一、定位函式(暴力法)

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;

int index(string s,string t,int pos){
    int i=pos;
    int j=0;
    int slen = s.length();
    int tlen = t.length();
    while(i<slen&&j<tlen){
        if(s[i]==t[j]){ i++,j++;}
        else{
            i=i-j+1;
               j=0;
        }
    }
    if(j==tlen) return i-tlen;
    return -1;
}

二、KMP的模式匹配

講點別的:

實際上KMP就是將模式串向右滑動,如果記錄每個模式串的前後相等的字串,然後下次可以直接往右移到指定的位置繼續匹配,從而減少無意義的匹配。

關鍵就是求next陣列,當P[j]==P[k]時,next[++j]=++k;當P[j]!=P[k]時,等於是自己模式匹配自己,k=next[k]。

ps:記住string物件的length()方法,返回的是一個unsigned int,不能拿它和int 型別的i(j)比較,int型別會被強轉為unsigned int,如果i是-1,那麼在unsigned int中是最大值(因為補碼,int和unsigned int不一樣)

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int next[30];
void get_next(string t){
	int i=0;
	next[0]=-1;
	int k=-1;
	int tlen = t.length();
	while(i<tlen-1){
		if(k==-1 || t[i]==t[k])
			next[++i]=++k;
		else k=next[k];
}
}
int KMP(string s,string t){
	int i=0;
	int j=0;
	get_next(t);
	int slen = s.length();
	int tlen = t.length();
	while(i<slen&&j<tlen){
		if(j==-1||s[i]==t[j]){
			i++,j++;
		}
		else {
		j=next[j];
	}
	}
	if(j==tlen) return i-j;
	else return -1;
}
int main(){
	string s1,s2;
	cin>>s1>>s2;
	cout<<KMP(s1,s2)<<endl;
}