1. 程式人生 > >KMP演算法介紹及時間複雜度分析

KMP演算法介紹及時間複雜度分析

概念:字串中 一個字元前面的字串 的字首與字尾的最長匹配長度(短的那個字串)

注意:字首與字尾不可以是整個子字串

例如:a b c a b c d , d位置的最長匹配長度為3,abc 與 abc 匹配

Next陣列:長度與字串長度一致,每個位置儲存對應字元的最長匹配長度

Next陣列求解:

1.初始位置,由於第一個字元前面沒有字元規定, Next[0] = -1; 由於第二個字元前面只有一個字元,Next[1] = 0.

2.後續位置,使用數學歸納法,根據前面已經求過的陣列值來求取Next[i];

設字串為str:

如果str[i] == str[x1] , Next[i + 1] = Next[i] + 1;

否則把str[i]與str[x2]比較,如果相等,Next[i + 1] = Next[x1] + 1;

直到走到字串的第一個位置,求取Next陣列的程式碼如下

vector<int> getNextArray(string str) {
	if (str.size() == 1) {
		vector<int> Next(1, -1);
		return Next;
	}
	vector<int> Next(5);
	Next[0] = -1;
	Next[1] = 0;
	int i = 2;//Next陣列中待求的位置
	int cm = 0;//與str[i - 1]比較的位置
	while (i < str.size()) {
		if (str[i - 1] == str[cm]) {
			Next[i++] = ++cm;//cm的值一直保持和Next[i - 1]一樣
		}
		else if (cm > 0)
		{
			cm = Next[cm];
		}
		else
		{
			Next[i++] = 0;//str[i - 1] != str[0]
		}
	}
	return Next;
}

2.KMP演算法的比較過程

X與Y位置不匹配,根據X位置的匹配串長度,可以把圓圈位置的字元直接與Y比較,完成加速過程

int getIndexOf(string str1, string str2) {
	vector<int> Next = getNextArray(str2);
	int i1 = 0;
	int i2 = 0;
	while (i1 < str1.size() && i2 < str2.size()) {
		if (str1[i1] == str2[i2]) {
			i1++;
			i2++;
		}
		else if (i2 != 0) {
			i2 = Next[i2];
		}
		else{
			i1++;//一直後退到str2[0]都不相等,只有i1向前走一個
		}
	}
	return i2 == str2.size() ? i1 - i2 : -1;//i2 == str2.size()代表str2走完了
}

 主函式如下:

int main()
{
	string match = "ababa";
	string str = "abcabcababaccc";
	cout << getIndexOf(str, match);
	return 0;
}