c语言主范式与编码,超详细!终于搞明白KMP算法
小伙伴們好久不見,今天將開設“數據結構與算法”專欄,一起梳理一遍硬核課程的重要知識點,那我們開始吧
正文
「字符串匹配」是計算機的基本任務之一,舉個栗子,有一個字符串“「aaaaaaca」",我想知道里面是否包含另一個字符串“「aaaac」”,該怎么辦?
這里就會使用到「串的模式匹配算法」,最常見的分別是傳統的「Brute-Force(暴力)算法」和「KMP算法」。
BF算法設計思想
1、主串和模式串逐個字符進行比較
2、當出現「字符串不相同」時,也就是「失配」時,主串的比較位置重置為起始位置的下一個字符位置,模式串的比較位置重置為起始位置
3、匹配成功后返回主串中匹配串的起始位置,否則就返回錯誤代碼
BF算法的設計缺陷及解決方案
在BF算法中,每次失配都需要回溯指向上次比較起始字符的下一個字符。通過觀察發現:在回溯的時候,已匹配似乎「有一部分」沒必要繼續比較了,這樣可以降低算法的「時間復雜度」
「KMP」算法的出現有效地解決了BF算法的缺陷。KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的。
但是這種算法相對于BF算法不太容易理解,網上也有很多解釋,但配圖有點少,總感覺差點意思,下面我通過畫圖的方式詳細介紹KMP算法的設計思想和工作原理
KMP算法設計思想
在匹配過程中出現字符比較不相等時,「主串 S」已比較的位置不回溯,「模式串 T」比較的位置進行移動
在匹配過程中有一個難題需要解決:如何計算「模式串 T」失配時的移動位數?經過三位牛人的研究,設計出了「部分匹配函數」
部分匹配函數
部分匹配函數是KMP算法中最難以理解的部分。首先需要理解「前綴」、「后綴」、「最大共有長度」的概念。
· 前綴:指除了最后一個字符以外,一個字符串的全部頭部組合
· 后綴:指除了第一個字符以外,一個字符串的全部尾部組合
· 最大共有長度(部分匹配值):指前綴和后綴中的最大共有元素,沒有則為0。例如“abab”的前綴為“a”、“ab”、“aba”,后綴為“b”、“ab”、“bab”,最大共有元素為“ab”,所以最大共有長度為 2
回顧一下KMP算法的匹配過程:
紅線框出的部分恰好就是失配時已匹配部分,“aaaa” 的最大共有元素為 “aaa”,這一部分字符就是不需要再重復進行比較直接跳過的字符
在代碼實現過程中,j 移動后的位置 = 模式串 T 的起始位置下標 + 部分匹配值。通常起始下標為 0,因此 j 移動后位置 = 部分匹配值,即 j = next[j],next[j] 就是「部分匹配函數」,j 為失配時的位置
因此接下來就成了對部分匹配函數的是實現。將 “aaaac” 以首字符起始的所有子串的最大共有長度枚舉出來,構成「部分匹配表」,它描述了失配時的下標 j 與部分匹配值的關系
部分匹配表則是通過模式串 T 的自匹配實現:
示例代碼(C語言哦):
/*KMP匹配算法*/
int?KMPCompare(HString?parent,?HString?child,?intpos)?{
int?next[255];
Get_Next(child,?next);
int?i?=?pos?-?1;
int?j?=?0;?????//j用于子串child中的起始位置
while?(i?
if?(j?==?0?||?parent.ch[i]?==?child.ch[j])?{
++i;
++j;
}
else?{
j?=?next[j];????//i不變,j后退
}
}
if?(j?==?child.length)?{
return?(i?+?1)?-?j;
}
return?0;
}
/*部分匹配函數的實現*/
void?Get_Next(HString?child,?int?*?next)?{
int?i?=?0;
int?j?=?-1;
next[0]?=?-1;???//不會用到
while?(i?
if?(j?==?-1?||?child.ch[i]?==?child.ch[j])?{
++i;
++j;
next[i]?=?j;
}
else?{
j?=?next[j];
}
}
}
void?main()?{
/*使用KMP算法匹配串*/
HString?parent,?child;
StrAssign_HeapString(&parent,?"BBC?ABCDAB?ABCDABCDABDE");
StrAssign_HeapString(&child,?"ABCDABD");
printf("Index?=?%d\n",?KMPCompare(parent,?child,?1));
}
復制代碼
關注即可提高學習效率!我是Aime菌,下期再見!Peace~
每天進步一點點,慢一點才能走得更快
總結
以上是生活随笔為你收集整理的c语言主范式与编码,超详细!终于搞明白KMP算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用C语言编写小学四则运算程序,用C语言编
- 下一篇: c语言char数字转int补位,关于ch