KMP演算法 究極版

2022-04-11 08:52:00 字數 2957 閱讀 2642

**翁振宇

字串匹配---kmp演算法

演算法實現一  

字串匹配的關鍵在於減少匹配次數。而kmp演算法的核心思想就是匹配陣列,根據匹配陣列的值來排程匹配字串的索引減少多餘的排程。

匹配陣列就是字串具有的相同字首、字尾的最大值。比如對於字串「ababacbbb」有:ta

baba

cbbb

\0next-10

0123

000-

j012

3456

78-1、  令next[0]=-1,從第二個字元(j=1)開始計算匹配陣列next的值。

2、  j=1,字元b前面只有乙個字元,該字元沒有字首、字尾因此next[1]=0。

3、  j=2,字元a前面的字串「ab」字首為a、字尾為b,並不相同。因此next[2]=0。

4、  j=3,字元b前面的字串「aba」字首有a、ab字尾有ba、a,相同的只有a長為1,因此next[3]=1。

5、  j=4,字元a前面的字串「abab」字首有a、ab、aba字尾有bab、ab、b,相同的只有ab長為2,因此next[4]=2。

6、  j=5,字元c前面的字串「ababa」字首有a、ab、aba、abab字尾有baba、aba、ba、a,相同的有a、aba,最長為3,因此next[5]=3。

7、  j=6,字元b前面的字串「ababac」字首有a、ab、aba、abab、ababa字尾有babac、abac、bac、ac、c沒有相同的前字尾,因此next[6]=0。

8、  j=7,字元b前面的字串「ababacb」字首有a、ab、aba、abab、ababa、ababac字尾有babacb、abacb、bacb、acb、cb、b沒有相同的前字尾,因此next[7]=0。

9、  j=8,字元b前面的字串「ababacbb」字首有a、ab、aba、abab、ababa、ababac、ababacb字尾有babacbb、abacbb、bacbb、acbb、cbb、bb、b沒有相同的前字尾,因此next[8]=0。

當匹配字串t與被匹配字串s比較時,如果出現某個字元不相等,則根據next陣列值調整匹配字串t的下標(j=next[j])。舉例來說t=「ababac」,s=「ababdababababac」:

1、  當s[i]與t[j]相同時直接遞增下標,當s串與t串遇到不相等的字元時,比如i=4時,則根據next匹配陣列值來調整t串的下標j。如果s[i]!=t[j]則令j=next[j]。如果改變j後s[i]       與t[j]仍然不相同,則繼續修改j直到j=-1為止。當j=-1時,令i、j均加1,t串與s串重新進行匹配。如下圖所示。

2、s[4]!=t[4],令j=next[4]=2,跳轉到t[2]繼續比較。

3、s[4]!=t[2],令j=next[2]=0,跳轉到t[0]繼續比較。

4、s[4]!=t[0],令j=next[0]=-1,則直接使i++,j++比較s[5]與t[0]。

5、從s[5]、t[0]開始連續5個字元相等,直到s[10]!=t[5],令j=next[5]=3,跳轉到t[3]比較。

6、從s[10]、t[3]開始連續兩個字元相同,直到s[12]!=t[5],令j=next[5]=3,跳轉到t[3]比較。

7、從s[12]、t[3]開始,直到t串結束餘下字元都相同,匹配成功。

**實現

void getnext(char *t, int *next)    //

獲取字串t的匹配陣列值

else

j=next[j]; //

j根據next[j]的值往回跳轉,直到出現字元相等或j為-1}}

int kmp(char *s, char *t) //

kmp演算法實現函式

else

j=next[j]; //

字元不相等是j值回溯

}return ((j0:i-length_t); //

返回t串在s串中第一次出現的位置

}

演算法實現二

在演算法實現一中kmp處理字串「aaaab」與「aaaacaaaab」的匹配時會會發現,j做了多次無用的跳轉。因為「aaaab」的next為「-1

0 1 2 3」,j就會出現從3依次跳轉到-1的情況,但是當j=3時發現『a』與『c』不相同那麼就不應該繼續比較後面的3個字元(都為『a』)。因此這裡需要對演算法一中取匹配陣列值的方法做一些調整。當出現「aaaab」這類情況時可以直接跳轉到首個字元『a』處。ta

aaab

cbbb

\0 next-10

1230

000-

next`

-1-1

-1-130

000-

j012345

678-

1、  根據next的值做一些調整。當t[i]==t[j]時,使t[i]的next[i]=next[j](i>j)。比如因為前面四個字元均為a,所以其next[i]均與next[0]相等。

2、  如果t[i]!=t[j],則直接將原來的next值保留(實際實現還是令next[i]=j(i>j))

**實現

void getnext(char *t, int *next)

else

j=next[j];

}}

vue 跨域處理究極版

如何在vue裡面優雅的解決跨域,路由衝突問題 當我們在路由裡面配置成以下 可以解決跨域問題 proxytable users 這種配置方式在一定程度上解決了跨域問題,但是會帶來一些問題,比如我們的vue 路由 也命名為 goods,這時候就會產生了衝突,如果專案中介面很多,都在這裡配置是很麻煩的,也...

氣泡排序究極奧義

原理 兩個for迴圈,外層for迴圈控制比較輪數 趟數 內層for迴圈比較每一輪中的前後兩項 次數 內層for迴圈每比較一輪就產生乙個當前迴圈的最大值 由於個別陣列本身的排列的特殊性 導致根本不需要將所有的趟數都排列完才可以 如下陣列 只需要排列一次即可 var arr 2,1,3,4,5,6,7,...

究極卡常神技

return x x p pchar buf 1 22 out 1 22 p1 buf,p2 buf ll p3 1,ff 0 define getchar p1 p2 p2 p1 buf fread buf,1,1 21,stdin p1 p2 eof p1 inline void flush i...