日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数据结构-查找】2.字符串(逐步演绎过程,超级详解KMP算法)

發(fā)布時(shí)間:2025/3/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数据结构-查找】2.字符串(逐步演绎过程,超级详解KMP算法) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

串的定義

串(string)是有0~n個(gè)字符組成的有限序列,一般記為
S=′a1a2…an′(n≥0)S = 'a_1a_2…a_n'(n≥0) S=a1?a2?an?(n0)
S 是字符串的名稱,aia_iai? 可以是字母數(shù)字或其他字符。

其中,串中任意連續(xù)的字符組成的子序列稱為該串的 子串

字符在串中的位置 通常是該字符在序列中的序號(hào)

子串在主串中的位置 指的是子串第一個(gè)字符在主串中的位置

串的模式匹配

子串的定位操作通常稱之為串的模式匹配,它的目的是要獲取子串在主串的位置。

一般的,我們想到的是一種暴力破解的方法

也就是說,從主串 S 的第 pos 個(gè)字符起,與模式串的一個(gè)字符比較,若相等,則繼續(xù)逐個(gè)比較主串和模式的后續(xù)字符;否則,從主串的下一個(gè)字符起,重新和模式的字符比較,以此類推,直至成功或失敗。

int IndexSubstring(string s, string sub, int pos) {int i = pos;int j = 0;while(i < s.size() && j < sub.size()) {if(s[i]==sub[j]) {i++;j++;} else {i = i - j + 1;j = 0;}}if(j >= sub.size()) return i - sub.size() + 1; // 查找成功else return 0; // 查找失敗 }

但這種暴力破解的算法的最壞時(shí)間復(fù)雜度為O(mn),m和n分別是主串和模式串的長度。


KMP算法——改進(jìn)的模式匹配算法

在回顧上面暴力破解的算法,我們可以得到,暴力算法每一次回溯都是回到模式串最初的起點(diǎn),事實(shí)上,這一步是可以改進(jìn)的。

【KMP算法】利用比較過的信息,i 指針不需要回溯,僅將子串向后滑動(dòng)一個(gè)合適的位置,并從這個(gè)位置開始和主串比較,這個(gè)合適的位置僅與 子串本身結(jié)構(gòu)有關(guān),與主串無關(guān)

【KMP算法】實(shí)際上是一種【備忘錄設(shè)計(jì)模式】,下面通過幾個(gè)步驟或許可以讓你了解這個(gè)算法的使用。

我們以主串 s='ababcabcacbab',模式串 sub=‘a(chǎn)bcac’

1.獲取模式串的 next 數(shù)組(備忘錄)

子串前綴后綴前后綴相同的最長
a--0
abab0
abca,abc,bc0
abcaa,ab,abca,ca,bca1
abcaca,ab,abc,abcac,ac,cac,bcac0

所以 模式串sub 的 next數(shù)組 為

sabcac
next00010

2.匹配過程

要滿足一個(gè)公式:移動(dòng)位數(shù) = 已經(jīng)匹配的位數(shù) - 對(duì)應(yīng)的部分匹配值

第一趟:發(fā)現(xiàn) a 與 c 不配

ababcabcacbab
abc

但是前面兩個(gè)字符 'ab' 是匹配的,查表可知,最后一個(gè)匹配字符 b 對(duì)應(yīng)匹配部分值為 0,按公式,計(jì)算 $ 2-0=2 $,所以,模式串向后移動(dòng) 2 位。

第2趟:模式串向后移動(dòng) 2 位后,發(fā)現(xiàn) b 與 c 不配

ababcabcacbab
abcac

但是前面兩個(gè)字符 'abca' 是匹配的,查表可知,最后一個(gè)匹配字符 a 對(duì)應(yīng)匹配部分值為 1 ,按公式,計(jì)算 4?1=34-1=34?1=3,所以,模式串向后移動(dòng) 3 位。

第3趟:模式串向后移動(dòng) 3 位后,匹配成功

ababcabcacbab
abcac

使用【KMP算法】后,時(shí)間復(fù)雜度變?yōu)榱薕(m+n)


KMP原理

已知公式:移動(dòng)位數(shù) = 已經(jīng)匹配的位數(shù) - 對(duì)應(yīng)的部分匹配值

改為代碼:
move=(j?1)?next[j?1]move = (j -1) - next[j-1] move=(j?1)?next[j?1]
優(yōu)化公式,如果我們將 next數(shù)組 向后挪一位,就不需要 next[j-1] ,只需要直接使用 next[j] 即可

sabcac
next00010
右移-10001

于是上述公式(2)既可以改為
move=(j?1)?next[j]move = (j -1) - next[j] move=(j?1)?next[j]
此時(shí),得到串移動(dòng)的公式
j=j?move=j?((j?1)?next[j])=next[j]+1j = j - move =j -((j -1) - next[j])=next[j]+1 j=j?move=j?((j?1)?next[j])=next[j]+1
進(jìn)一步優(yōu)化,我們可以將右移后是 next數(shù)組 總體+1,那么,最后的數(shù)組就變成了
j=next[j]j = next[j] j=next[j]

sabcac
next00010
右移-10001
右移+101112

最后一行的意思是,把模式串的第 next[j] 個(gè)值,移動(dòng) j 這個(gè)位置。或者說,從模式串的第 next[j] 個(gè)數(shù)組開始查找,主串繼續(xù)移動(dòng)即可。

3.使用了改進(jìn)后的next數(shù)組再匹配過程

第一趟:發(fā)現(xiàn) a 與 c 不配

ababcabcacbab
abc

在 c(pos=2) 這個(gè)位置匹配失敗,查表得,c 的對(duì)應(yīng)值是 1 ,也就是將模式串的第一個(gè)字符 (a) 移到 c(pos=2) 這個(gè)位置

第2趟:模式串向后移動(dòng) 2 位后,發(fā)現(xiàn) b 與 c 不配

ababcabcacbab
abcac

在 c(pos=6) 這個(gè)位置匹配失敗,查表得,c 的對(duì)應(yīng)值是 2 ,也就是將模式串的第二個(gè)字符 (b) 移到 c(pos=6) 這個(gè)位置

第3趟:模式串向后移動(dòng) 3 位后,匹配成功

ababcabcacbab
abcac

參考代碼

獲取next數(shù)組

void getNext(string sub, int next) {int i = 0;int j = 0;next[0] = 0;while(i<sub.size()) {if(j == 0|| s[i]==s[j]){i++;j++;next[i] = j;} else {j = next[j];}} }

【KMP算法】

int Index(string s, string sub, int next[], inr pos) {int i = pos;int j = 0;while(i<s.size()&&j<sub.size()) {if(j==0||s[i]==sub[j]){i++;j++; } else {j = next[j]; // 模式串右移}if(j >= sub.size()) {return i - sub.size() + 1;} eles {return 0;}} }

總結(jié)

以上是生活随笔為你收集整理的【数据结构-查找】2.字符串(逐步演绎过程,超级详解KMP算法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。