精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

教你從頭到尾徹底理解KMP算法

移動開發 算法
本文由簡單的字符串匹配算法開始,經Rabin-Karp算法,最后到KMP算法,教你從頭到尾徹底理解KMP算法。

[[121931]]

本文參考:數據結構(c語言版) 李云清等編著、算法導論

引言:

在文本編輯中,我們經常要在一段文本中某個特定的位置找出 某個特定的字符或模式。

由此,便產生了字符串的匹配問題。

本文由簡單的字符串匹配算法開始,經Rabin-Karp算法,***到KMP算法,教你從頭到尾徹底理解KMP算法。

來看算法導論一書上關于此字符串問題的定義:

假設文本是一個長度為n的數組T[1...n],模式是一個長度為m<=n的數組P[1....m]。

進一步假設P和T的元素都是屬于有限字母表Σ.中的字符。

依據上圖,再來解釋下字符串匹配問題。目標是找出所有在文本T=abcabaabcaabac中的模式P=abaa所有出現。

該模式僅在文本中出現了一次,在位移s=3處。位移s=3是有效位移。

一、簡單的字符串匹配算法

簡單的字符串匹配算法用一個循環來找出所有有效位移,

該循環對n-m+1個可能的每一個s值檢查條件P[1....m]=T[s+1....s+m]。

NAIVE-STRING-MATCHER(T, P)

1 n ← length[T]

2 m ← length[P]

3 for s ← 0 to n - m

4 do if P[1 ‥ m] = T[s + 1 ‥ s + m]

//對n-m+1個可能的位移s中的每一個值,比較相應的字符的循環必須執行m次。

5 then print "Pattern occurs with shift" s

簡單字符串匹配算法,上圖針對文本T=acaabc 和模式P=aab。

上述第4行代碼,n-m+1個可能的位移s中的每一個值,比較相應的字符的循環必須執行m次。

所以,在最壞情況下,此簡單模式匹配算法的運行時間為O((n-m+1)m)。

--------------------------------

下面我再來舉個具體例子,并給出一具體運行程序:

對于目的字串target是banananobano,要匹配的字串pattern是nano,的情況,

下面是匹配過程,原理很簡單,只要先和target字串的***個字符比較,

如果相同就比較下一個,如果不同就把pattern右移一下,

之后再從pattern的每一個字符比較,這個算法的運行過程如下圖。

//index表示的每n次匹配的情形。

  1. #include<iostream> 
  2. #include<string> 
  3. using namespace std; 
  4. int match(const string& target,const string& pattern) 
  5. int target_length = target.size(); 
  6. int pattern_length = pattern.size(); 
  7. int target_index = 0; 
  8. int pattern_index = 0; 
  9. while(target_index < target_length && pattern_index < pattern_length) 
  10. if(target[target_index]==pattern[pattern_index]) 
  11. ++target_index; 
  12. ++pattern_index; 
  13. else 
  14. target_index -= (pattern_index-1); 
  15. pattern_index = 0; 
  16. if(pattern_index == pattern_length) 
  17. return target_index - pattern_length; 
  18. else 
  19. return -1; 
  20. int main() 
  21. cout<<match("banananobano","nano")<<endl; 
  22. return 0; 
  23. //運行結果為4。

上面的算法進間復雜度是O(pattern_length*target_length),

我們主要把時間浪費在什么地方呢,

觀查index =2那一步,我們已經匹配了3個字符,而第4個字符是不匹配的,這時我們已經匹配的字符序列是nan,

此時如果向右移動一位,那么nan***匹配的字符序列將是an,這肯定是不能匹配的,

之后再右移一位,匹配的是nan***匹配的序列是n,這是可以匹配的。

如果我們事先知道pattern本身的這些信息就不用每次匹配失敗后都把target_index回退回去,

這種回退就浪費了很多不必要的時間,如果能事先計算出pattern本身的這些性質,

那么就可以在失配時直接把pattern移動到下一個可能的位置,

把其中根本不可能匹配的過程省略掉,

如上表所示我們在index=2時失配,此時就可以直接把pattern移動到index=4的狀態,

kmp算法就是從此出發。

二、KMP算法

1、 覆蓋函數(overlay_function)

覆蓋函數所表征的是pattern本身的性質,可以讓為其表征的是pattern從左開始的所有連續子串的自我覆蓋程度。

比如如下的字串,abaabcaba

由于計數是從0始的,因此覆蓋函數的值為0說明有1個匹配,對于從0還是從來開始計數是偏好問題,

具體請自行調整,其中-1表示沒有覆蓋,那么何為覆蓋呢,下面比較數學的來看一下定義,比如對于序列

a0a1...aj-1 aj

要找到一個k,使它滿足

a0a1...ak-1ak=aj-kaj-k+1...aj-1aj

而沒有更大的k滿足這個條件,就是說要找到盡可能大k,使pattern前k字符與后k字符相匹配,k要盡可能的大,

原因是如果有比較大的k存在,而我們選擇較小的滿足條件的k,

那么當失配時,我們就會使pattern向右移動的位置變大,而較少的移動位置是存在匹配的,這樣我們就會把可能匹配的結果丟失。

比如下面的序列,

在紅色部分失配,正確的結果是k=1的情況,把pattern右移4位,如果選擇k=0,右移5位則會產生錯誤。

計算這個overlay函數的方法可以采用遞推,可以想象如果對于pattern的前j個字符,如果覆蓋函數值為k

a0a1...ak-1ak=aj-kaj-k+1...aj-1aj

則對于pattern的前j+1序列字符,則有如下可能

⑴ pattern[k+1]==pattern[j+1] 此時overlay(j+1)=k+1=overlay(j)+1

⑵ pattern[k+1]≠pattern[j+1] 此時只能在pattern前k+1個子符組所的子串中找到相應的overlay函數,h=overlay(k),如果此時pattern[h+1]==pattern[j+1],則overlay(j+1)=h+1否則重復(2)過程.

下面給出一段計算覆蓋函數的代碼:

 

  1. #include<iostream> 
  2. #include<string> 
  3. using namespace std; 
  4. void compute_overlay(const string& pattern) 
  5. const int pattern_length = pattern.size(); 
  6. int *overlay_function = new int[pattern_length]; 
  7. int index; 
  8. overlay_function[0] = -1; 
  9. for(int i=1;i<pattern_length;++i) 
  10. index = overlay_function[i-1]; 
  11. //store previous fail position k to index; 
  12. while(index>=0 && pattern[i]!=pattern[index+1]) 
  13. index = overlay_function[index]; 
  14. if(pattern[i]==pattern[index+1]) 
  15. overlay_function[i] = index + 1; 
  16. else 
  17. overlay_function[i] = -1; 
  18. for(i=0;i<pattern_length;++i) 
  19. cout<<overlay_function[i]<<endl; 
  20. delete[] overlay_function; 
  21. int main() 
  22. string pattern = "abaabcaba"
  23. compute_overlay(pattern); 
  24. return 0; 

運行結果為:

-1

-1

0

0

1

-1

0

1

2

Press any key to continue

-------------------------------------

2、kmp算法

有了覆蓋函數,那么實現kmp算法就是很簡單的了,我們的原則還是從左向右匹配,但是當失配發生時,我們不用把target_index向回移 動,target_index前面已經匹配過的部分在pattern自身就能體現出來,只要動pattern_index就可以了。

當發生在j長度失配時,只要把pattern向右移動j-overlay(j)長度就可以了。

如果失配時pattern_index==0,相當于pattern***個字符就不匹配,

這時就應該把target_index加1,向右移動1位就可以了。

ok,下圖就是KMP算法的過程(紅色即是采用KMP算法的執行過程):

ok,***給出KMP算法實現的c++代碼:

  1. #include<iostream> 
  2. #include<string> 
  3. #include<vector> 
  4. using namespace std; 
  5. int kmp_find(const string& target,const string& pattern) 
  6. const int target_length = target.size(); 
  7. const int pattern_length = pattern.size(); 
  8. int * overlay_value = new int[pattern_length]; 
  9. overlay_value[0] = -1; 
  10. int index = 0; 
  11. for(int i=1;i<pattern_length;++i) 
  12. index = overlay_value[i-1]; 
  13. while(index>=0 && pattern[index+1]!=pattern[i]) 
  14. index = overlay_value[index]; 
  15. if(pattern[index+1]==pattern[i]) 
  16. overlay_value[i] = index +1; 
  17. else 
  18. overlay_value[i] = -1; 
  19. //match algorithm start 
  20. int pattern_index = 0; 
  21. int target_index = 0; 
  22. while(pattern_index<pattern_length&&target_index<target_length) 
  23. if(target[target_index]==pattern[pattern_index]) 
  24. ++target_index; 
  25. ++pattern_index; 
  26. else if(pattern_index==0) 
  27. ++target_index; 
  28. else 
  29. pattern_index = overlay_value[pattern_index-1]+1; 
  30. if(pattern_index==pattern_length) 
  31. return target_index-pattern_index; 
  32. else 
  33. return -1; 
  34. delete [] overlay_value; 
  35. int main() 
  36. string source = " annbcdanacadsannannabnna"
  37. string pattern = " annacanna"
  38. cout<<kmp_find(source,pattern)<<endl; 
  39. return 0; 
  40. //運行結果為 -1. 

三、kmp算法的來源

kmp如此精巧,那么它是怎么來的呢,為什么要三個人合力才能想出來。其實就算沒有kmp算法,人們在字符匹配中也能找到相同高效的算法。這種算法,最終 相當于kmp算法,只是這種算法的出發點不是覆蓋函數,不是直接從匹配的內在原理出發,而使用此方法的計算的覆蓋函數過程序復雜且不易被理解,但是一但找 到這個覆蓋函數,那以后使用同一pattern匹配時的效率就和kmp一樣了,其實這種算法找到的函數不應叫做覆蓋函數,因為在尋找過程中根本沒有考慮是 否覆蓋的問題。

說了這么半天那么這種方法是什么呢,這種方法是就大名鼎鼎的確定的有限自動機(Deterministic finite state automaton DFA),DFA可識別的文法是3型文法,又叫正規文法或是正則文法,既然可以識別正則文法,那么識別確定的字串肯定不是問題(確定字串是正則式的一個子 集)。對于如何構造DFA,是有一個完整的算法,這里不做介紹了。在識別確定的字串時使用DFA實在是大材小用,DFA可以識別更加通用的正則表達式,而 用通用的構建DFA的方法來識別確定的字串,那這個overhead就顯得太大了。

kmp算法的可貴之處是從字符匹配的問題本身特點出發,巧妙使用覆蓋函數這一表征pattern自身特點的這一概念來快速直接生成識別字串的DFA,因此對于kmp這種算法,理解這種算法高中數學就可以了,但是如果想從無到有設計出這種算法是要求有比較深的數學功底的。

原文:http://www.2cto.com/kf/201104/87381.html

作者聲明:個人July 對此24個經典算法系列,享有版權,轉載請注明出處。

責任編輯:閆佳明 來源: 2cto
相關推薦

2013-10-10 10:34:47

哈希算法

2013-05-02 11:21:36

iOS開發流程

2021-11-08 17:03:13

IO模型

2015-09-21 09:48:48

私有云云架構云管理

2021-04-21 10:00:08

MySQL索引數據庫

2019-08-21 08:54:46

垃圾回收Java算法

2016-03-09 09:42:15

App產品經理項目啟動

2024-07-03 11:23:14

2014-12-24 11:34:23

CoreOSWordPress集群部署

2022-04-24 11:06:54

SpringBootjar代碼

2021-09-07 07:55:22

Linux CPULinux 系統

2017-03-25 21:13:38

JavaScript排序

2021-08-09 06:57:42

代碼重定位Linux

2020-05-28 08:59:40

Python機器學習開發

2021-05-13 08:55:33

Android架構功能

2020-08-17 09:25:51

Docker容器技術

2025-09-16 09:06:00

OpenAI模型AI

2024-08-26 15:20:45

2019-02-20 13:57:48

游戲服務器框架

2019-09-10 09:40:11

游戲服務器框架
點贊
收藏

51CTO技術棧公眾號

福利所第一导航| 黄色一级在线视频| 国内老熟妇对白xxxxhd| 亚洲国内欧美| 亚洲全黄一级网站| 91欧美一区二区三区| 理论片午夜视频在线观看| 久久综合av免费| 91九色蝌蚪国产| 可以免费在线观看的av| 欧美国产美女| 日韩精品福利在线| 亚洲一二三不卡| 三级在线观看视频| 亚洲丝袜自拍清纯另类| 久久久久久久有限公司| 国产又黄又粗又长| 免费久久99精品国产自在现线| 久久久久北条麻妃免费看| 中国一级特黄录像播放| 天堂久久一区| 色天天综合久久久久综合片| 黄色a级片免费看| av成人手机在线| eeuss国产一区二区三区| 国产精品一区专区欧美日韩| 麻豆久久久久久久久久| 牛夜精品久久久久久久99黑人| 亚洲一级黄色片| 午夜剧场免费看| 精品一区二区三区四区五区 | 天堂综合在线播放| 日韩欧美在线观看| 欧美啪啪免费视频| 欧美一卡二卡| 亚洲精品国产视频| 99精品一级欧美片免费播放| 一区二区三区视频网站| 国产亚洲欧美一级| 免费观看成人高| 色鬼7777久久| 97精品电影院| 久久精品五月婷婷| 天天操天天操天天操| 国产成人亚洲综合a∨猫咪| 91精品久久久久久久久久久久久| 在线视频精品免费| 肉丝袜脚交视频一区二区| 51午夜精品视频| 欧美精品亚洲精品日韩精品| 在线欧美不卡| 久久久噜噜噜久噜久久| 国产污片在线观看| a91a精品视频在线观看| 97在线视频一区| 人妻 日韩精品 中文字幕| 国产亚洲综合精品| 欧美在线免费看| 欧美男人天堂网| 日韩电影免费一区| 国产欧美婷婷中文| 国产又大又粗又硬| 国产精品一卡二| 国产精品xxx在线观看www| 蜜臀av在线观看| 99re这里都是精品| 欧美韩国日本精品一区二区三区| 日本福利片在线| 欧美国产欧美亚州国产日韩mv天天看完整 | 无码精品a∨在线观看中文| 国产拍在线视频| 一本色道久久综合亚洲aⅴ蜜桃 | 成人午夜精品视频| 久久99精品视频| 51国偷自产一区二区三区的来源| 亚洲国产www| 91免费在线播放| 亚洲高清在线观看一区| av大片在线| 婷婷丁香激情综合| 亚洲一区在线不卡| 欧美国产中文高清| 亚洲精品有码在线| 亚洲欧美日韩第一页| 亚洲精品成人影院| 91精品国产91久久| 五月激情丁香网| 国产一区二区三区久久悠悠色av| 国产精品一国产精品最新章节| 手机福利在线| 日韩毛片精品高清免费| 成人免费aaa| 久久青草视频| 日韩精品免费一线在线观看| 自拍偷拍第9页| 亚洲国产一区二区精品专区| 国产精品美女999| 韩国av免费在线| 亚洲最大的网站| 国产精品国产亚洲精品看不卡| 麻豆av在线播放| 色婷婷国产精品综合在线观看| 一起操在线视频| 成人知道污网站| 在线精品视频视频中文字幕| 麻豆changesxxx国产| 美女网站久久| 成人18视频| aaa在线观看| 精品福利视频导航| 狠狠干狠狠操视频| 亚洲区小说区图片区qvod| 日韩在线视频网站| 亚洲第一精品在线观看| 国内精品久久久久影院一蜜桃| 蜜桃视频成人| eeuss鲁一区二区三区| 欧美三区免费完整视频在线观看| 中文在线观看免费视频| 香蕉av一区二区| 国产精品91在线观看| 内射后入在线观看一区| 亚洲日本va午夜在线影院| 日日摸天天爽天天爽视频| 国产96在线亚洲| 久国内精品在线| 国产一区二区波多野结衣| 国产亚洲欧美色| 黄色动漫在线免费看| 天堂久久av| 久久视频这里只有精品| 国产精品成人久久久| 久久综合资源网| 精品久久久久久久久久中文字幕| 亚洲视频国产| 久久6精品影院| 国产www免费观看| 亚洲欧美经典视频| 免费一区二区三区在线观看| 精品福利久久久| 国产成人精品亚洲精品| 亚洲av激情无码专区在线播放| 亚洲在线一区二区三区| 波多野吉衣在线视频| 欧美激情视频一区二区三区在线播放| 成人福利视频网| melody高清在线观看| 在线视频欧美精品| 精品人妻一区二区三区蜜桃视频| 久久九九精品| 午夜精品区一区二区三| 嫩草伊人久久精品少妇av杨幂| 一区二区三区无码高清视频| 18国产免费视频| 国产精品久久久久久久久动漫 | gogogogo高清视频在线| 欧美精品丝袜中出| 91高清免费观看| 国产成人在线看| 人妻久久久一区二区三区| 欧美国产极品| 国产精品久久久久久久久久ktv | 日韩高清电影免费| 91av视频在线观看| 国模精品一区二区| 欧美日韩在线直播| 国产精品久久久久久久精| 国产98色在线|日韩| 欧美 日本 亚洲| 欧美精品羞羞答答| 成人免费淫片视频软件| 色呦呦在线观看视频| 亚洲成人av片| 激情网站在线观看| 亚洲欧美日韩久久| 日韩精品视频一区二区| 媚黑女一区二区| 自拍偷拍视频在线| 精品女人视频| 国产精品午夜国产小视频| 成人video亚洲精品| 精品日韩av一区二区| av资源免费观看| 国产精品久久毛片a| www.偷拍.com| 国产精品日韩| 天天综合中文字幕| 日韩精品a在线观看91| 国产精品免费一区二区三区都可以 | 中文字幕成人| 亚洲2020天天堂在线观看| 91视频在线观看| 亚洲高清一区二| 中文字幕在线一| 精品久久久精品| 欧美三级黄色大片| 91免费视频大全| 三大队在线观看| 青青草成人在线观看| 黄色一级大片免费| 色综合中文网| 国产精品av一区| 欧美视频第一| 全球成人中文在线| 欧美xxxx黑人又粗又长| 一区二区三区久久精品| 人人妻人人澡人人爽人人欧美一区| 欧美日韩国产一区| www.中文字幕在线观看| 亚洲黄色免费网站| 一本色道久久88| 91色在线porny| 亚洲一级Av无码毛片久久精品| 久久精品国产一区二区| 欧美成人一区二区在线观看| 午夜亚洲福利| 精品一区二区成人免费视频| 九色成人国产蝌蚪91| 国产精品国产精品| 国产va免费精品观看精品| 国产成人avxxxxx在线看| 成人影院在线播放| 久久成人这里只有精品| 婷婷免费在线视频| 中文字幕av一区二区三区谷原希美| 五月婷婷在线播放| 亚洲成人黄色在线观看| 精品乱子伦一区二区| 欧美精品vⅰdeose4hd| 最近中文在线观看| 色哟哟精品一区| 久久黄色精品视频| 欧美日韩国产激情| 日韩精品一卡二卡| 五月天亚洲婷婷| 精品一区二区三区人妻| 一区二区三区在线视频免费观看| 国产3级在线观看| 国产精品久久久久三级| 欧美xxxx精品| 中文字幕一区二区三区视频| 波兰性xxxxx极品hd| 国产精品久久福利| 美国精品一区二区| 中文字幕av一区二区三区免费看 | 国产精品秘入口| 一本色道久久综合狠狠躁篇的优点 | 日韩中文av在线| 男人资源在线播放| 色综合伊人色综合网站| 免费大片黄在线| 欧美成人免费播放| 欧美黄色视屏| 久久久免费精品| 一级毛片久久久| 国产精品国内视频| 久久久久黄色| 99re资源| 欧美日韩导航| 日韩成人在线资源| 久久精品国产68国产精品亚洲| 色中文字幕在线观看| 欧美精品日韩| 欧美 日韩 亚洲 一区| 老司机一区二区三区| 欧美午夜aaaaaa免费视频| 狠狠色综合色综合网络| 免费在线观看日韩av| 99re这里只有精品视频首页| 日韩毛片无码永久免费看| 亚洲欧洲日韩一区二区三区| 久久久精品91| 日本道精品一区二区三区| 中文字幕在线2018| 日韩精品中午字幕| 日本国产在线| 久久综合伊人77777蜜臀| 国产va在线视频| 国产精品美女在线观看| 亚洲国产aⅴ精品一区二区| 国产激情美女久久久久久吹潮| 岳的好大精品一区二区三区| 中文字幕色一区二区| 亚洲精品孕妇| 自拍偷拍一区二区三区四区| 成人性视频免费网站| www亚洲色图| 亚洲一区二区三区视频在线播放| 久久免费激情视频| 91精品国产综合久久国产大片| 天天av天天翘| 色久欧美在线视频观看| 51漫画成人app入口| 国产精品久久在线观看| 亚洲2区在线| 亚洲精品免费在线看| 亚洲国产欧美国产综合一区| 色播五月综合网| 99精品欧美一区二区蜜桃免费 | 成人在线免费观看| 欧美精品videossex88| 六九午夜精品视频| 久久亚洲高清| 午夜国产精品视频| 国产三级三级三级看三级| 成人午夜视频网站| 亚洲区一区二区三| 色呦呦国产精品| 天天干,夜夜爽| 久久人体大胆视频| 无人区在线高清完整免费版 一区二| 99久久伊人精品影院| 久久国产成人午夜av影院宅| 99热成人精品热久久66| 福利一区二区在线| 亚洲波多野结衣| 欧美视频一区二区| 美女欧美视频在线观看免费| 久久频这里精品99香蕉| 欧美经典影片视频网站| 亚洲精品在线观看免费| 亚洲欧美春色| 精品影片一区二区入口| 亚洲午夜激情网站| www久久久久久| 超碰精品一区二区三区乱码| 欧美123区| 日本免费高清一区| 乱人伦精品视频在线观看| 国产精品伦子伦| 午夜影视日本亚洲欧洲精品| www.国产三级| 精品中文字幕在线2019| 国产免费区一区二区三视频免费| 亚洲精品一卡二卡三卡四卡| 日韩电影免费在线| 中文字幕 自拍| 91黄色免费观看| av在线日韩国产精品| 国产精品中文字幕久久久| 成人在线国产| jizz18女人| 国产精品国产三级国产| 亚洲综合精品在线| 中文字幕精品一区久久久久| 四虎精品永久免费| 正在播放一区| 国产精品一区二区果冻传媒| 免费人成年激情视频在线观看| 欧美www视频| bl在线肉h视频大尺度| 精品一卡二卡三卡四卡日本乱码| 国产精品一二| 久久久视频6r| 欧美日韩大陆一区二区| 在线激情网站| 超碰97网站| 亚洲人妖在线| 国产精品无码久久久久一区二区| 色激情天天射综合网| a天堂中文在线| 97神马电影| 国产亚洲精品bv在线观看| 久久久久无码精品国产sm果冻| 欧美日韩中文国产| av毛片在线播放| 国产一区二区在线网站| 久久激情久久| 国产第一页浮力| 亚洲第一免费网站| 中文日产幕无线码一区二区| 亚洲一区二区三区乱码| 国产精品主播直播| 亚州国产精品视频| 中文字幕精品—区二区| 香蕉免费一区二区三区在线观看 | 日本三级片在线观看| 精品中文字幕久久久久久| 台湾天天综合人成在线| 国产亚洲黄色片| 欧美激情一区二区三区在线| 精品久久久免费视频| 日韩av成人在线观看| 亚洲国产一成人久久精品| 国模私拍在线观看| 欧美日韩免费一区二区三区视频| 污污影院在线观看| 欧洲精品一区色| 国产高清亚洲一区| 中文字幕免费观看| 精品自拍视频在线观看| 国产成人影院| 亚洲少妇中文字幕| 欧美丝袜丝交足nylons图片| 国产精品69xx| 三年中国中文在线观看免费播放 | 亚洲国产精品中文| 成人在线免费电影网站| 亚洲美免无码中文字幕在线 | 国偷自拍第113页|