數據結構之KMP算法next數組


  我們要找到一個短字符串(模式串)在另一個長字符串(原始串)中的起始位置,也就是模式匹配,最關鍵的是找到next數組。最簡單的算法就是用雙層循環來解決,但是這種算法效率低,kmp算法是針對模式串自身的特點,當失配時,能夠利用next數組得到的信息直接跳過不可能匹配成功的位置字符。例如模式字符串“ababaaaba”,假設當匹配到第6個字符“a”發生錯誤,傳統方法是原始字符串往后移動一個,但是原始串顯然第2個字符是b(因為之前匹配過了),不可能是模式串的起始字符,而next會發現從原始串的第1個字符開始的“aba”和第3個字符開始的“aba”是一樣的,所以直接將模式串的第1個字符和原始串的往后移動2個的字符比較,而此時直接用模式串第4個字符與之前原始串中失配的字符比也就是說模式串中第6個位置和第4個位置的字符位置等價,你失配了我來,因為他們前面有相同的串,而且其中一個是從模式串的起始位置開始的,這也就是next數組的定義。

  說的這么詳細是因為考研期間這個部分非常難,我本人也是用了幾天才參透這里面的原理,畢竟是非常著名的算法,不是背上來代碼那么簡單。​​

  字符串​一般是從編號1開始,第0個位置存放長度,簡單起見下面的代碼簡化表示。

 

#define _CRT_SECURE_NO_DEPRECATE//vs編譯器編譯c語言需要加此條語句
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_next(int *next, char *Array,int len) /*求NEXT[]的值*/
{
	int i = 1, j = 0;  //如果字符串不是從編號1開始,則初始化i=0,j=-1,i<len-1
	next[1] = 0;//初始化第一個字符的next值為0
	while (i < len)//整個過程中i變量一遍走過,而j變量可能會回溯,i一直在j后面
	{
		if (j == 0 || Array[i] ==Array[j])//起始或者字符有重復,那么下一個位置i++和j++的位置等價,
		{
			i++;
			j++;
			if (Array[i] == Array[j])
               next[i] = next[j];   //優化找到最開始的等價位,等價位的等價位
			else
				next[i] = j;
		}
		else
			j = next[j];  //回溯,正是利用了next數組本身的回溯的功能
	}
}
int main()
{
	char A[] = "0ababaaaba";//為了使得字符數據從編號1開始
	int next[sizeof(A)-1] = { 0 };//初始化
	int len = sizeof(A)-1;
	get_next(next, A,len);
	for (int i = 1; i < len;i++)
		printf("%d ",next[i]);
	system("pause");//vs運行需要加此條代碼
	return 0;
}

 

  

 

運行結果:​若為未改進的算法,模式串“ababaaaba”的next運行結果為

  0 1 1 2 3 4 2 2 3,

  改進算法運行結果為0 1 0 1 0 4 2 1 0。

  考試題也有可能不考代碼,我的經驗是先根據算法寫出為改進的,然后從頭開始對應的字符一樣就改為前面那個字符的next值,以此類推。​


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM