資料結構7 串(KMP next陣列)

2021-09-10 02:28:03 字數 2328 閱讀 1447

串:

串(string)是由零個或多個字元組成的有序序列,又叫字串。

字串的匹配:

串s和t存在,t時非空串,若主串中存在和串t值相同的字串,則返回它在主串s中第pos個字元之後第一次出現的位置,否則返回-1。

這種子串的定位操作通常稱作串的模式匹配。一般把s稱為主串,t稱為模式串。

一般字串的匹配演算法主要有:

(1)樸素的字串匹配演算法(***** string matching algorithm)

(2)knuth-morris-pratt字串匹配演算法(kmp演算法)

假設我們要從s="goodgoogle"尋找t="google"。

樸素的字串匹配演算法

(1)將主串中的第乙個和子串中的第乙個比較,如果匹配成功,則將主串和子串中的第二個比較。如果兩個串**現不相同的情況,就將主串的第二個和子串的第乙個比較。這樣一直到匹配完成或者,主串完結。

思想比較簡單,程式也比較好實現。

int ******string(string mainstr, string modestr, int pos)

else

if (j == modestrlen)

}return p;

}

kmp演算法

觀察上面的樸素的字串匹配演算法我們就會發現,在第一次匹配失敗後,其實在從主串的第二位置繼續尋找是大可不必的,因為「google」中不相同的元素,所以我們可以在主串中下標為4的位置開始重新開始匹配,這樣就可以減少比較的次數。這就是kmp的基本思路。那如何計算匹配失敗後重新開始匹配的位置,就是kmp演算法的關鍵(next陣列)。

kmp的演算法流程:

假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置

(1)如果j = -1,或者當前字元匹配成功(即s[i] == p[j]),都令i++,j++,繼續匹配下乙個字元;

(2) 如果j != -1,且當前字元匹配失敗(即s[i] != p[j]),則令 i 不變,j = next[j]。

這是問題的關鍵就轉化成如何求next陣列(kmp的核心問題):

next陣列中儲存的是除當前字元外最長公共字首字尾。那麼什麼是最長公共字首字尾那?簡單來說就是一段字元前面和後面都相同的部分的長度,例如:aba,字首有(a,ab)字尾有(a,ba),那aba的最長公共字首字尾就是1,同理abab的最長公共字首字尾就是2。但next中儲存的是除當前字元外最長公共字首字尾,需要將第一步中求出的陣列,整體後移一位,然後將第0位的元素置成-1。next陣列雖然描述起來很簡單,在給定乙個特定的串下用筆計算也不難,但問題在是模式串是不確定的,所以演算法的理解上還是有一定的困難的,尤其是匹配失敗後的回溯過程。下面是求解next陣列的**:

/*

(1)先生成最長公共字首字尾表,不做轉化。

(2)轉化為next陣列。

*/void makenext(string modestr, vector& pnext)

/*退出迴圈:

(1)j==0,沒有在前面尋找到和mode[i]相同的元素

(2)modestr[i]==modestr[j],在前面尋找到了和mode[i]相同的元素。

*/if (modestr[i] == modestr[j])

pnext.push_back(j);

++i;

} //轉化為next陣列

pnext.insert(pnext.begin(), -1);

pnext.pop_back();

}

next陣列一旦求出,那麼kmp問題也就完成了99%了,下面是kmp演算法:

int kmp(string mainstr, string modestr)

} else

}return pos;

}

如果理解可以看看這篇文章:教你從頭到尾徹底理解kmp演算法

資料結構 陣列,字串

陣列 字串是兩種最基本的資料結構,使用連續記憶體分別存數字和字元,並按照順序儲存。str indexofnew str indexoforiginal str indexofnew str indexoforiginal indexofnew bool duplicate int numbers,i...

資料結構之串與陣列

關於串 串是由零個或多個字元組成的有限序列,它的邏輯結構與線性表極為相似,可看作是一種特殊的線性表。串的元素序號從0開始。相關概念 1.串的長度 串中所包含的字元個數 2.空串 長度為0的串 在c語言中,串一般使用不可顯示的字元 0 作為串的結束符。3.子串 串中任意個連續的字元組成的子串行稱為串的...

資料結構 串

輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。結果請按字母順序輸出。我們求整個字串的排列,可以看成兩步 首先求所有可能出現在第乙個位置的字元,即把第乙個字元和後面所有的字元交換。第...