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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

模式匹配算法----KMP算法以及next数组的解法

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 模式匹配算法----KMP算法以及next数组的解法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

KMP算法:求字符串匹配(也叫模式匹配)的算法,即給定一個字符串,求其某一子串在其中出現的位置。

普通模式匹配

例如:給定字符串為abcabaaabaabcac,求其子串abaabcac在其中出現的位置。

結果為7

對于這種問題,沒有經驗的編程者通常會采用逐個匹配的方法,來得出結果。這就是最簡單一種算法思想。

1. 逐個進行比較,如果相同,就繼續比較下一個,但是我們可以看到下圖中,c與a不相同,這就是所謂的“失配”。

2. 當發生失配,我們會將子字符串逐個后移,直到新的匹配建立,再逐個比較

3.

4.

5.

6.

7.

根據上面的方法,我們可以看到第二步有兩個圖,這是為什么呢?這是因為當出現失配時候,字符串每次后移一個的方法,不能夠立刻建立匹配,還需要繼續后移才能建立。也就是說,這種情況下,后移兩個才能建立匹配。

當然這個例子比較小,只出現了兩次這種情況,但是如果是較大的數據,這種冗余操作是十分低效的。這也就是KMP算法優化的地方。

KMP算法--next[]

KMP算法會創建一個next[]數組,用來保存一個字符失配后,到底跳轉到第幾個的位置才能更快速的建立匹配。這里用了跳轉這個詞,因為并不是向后移動next[i]位,而應該是直接跳轉到相應的位置,使失配位與第next[i]位相對。這個數組是KMP算法的核心。

下面以字符串abaabcac為例,求解next數組,模式匹配的數組下標從1開始(這個算法推薦這么做,很多事情沒有那么多理由)

?

next數組按照最長相等前后綴長度求解:

next[1],字符串“a”,前綴{},后綴{},沒有相等前后綴,next記為0。要注意,前后綴均不包括整個串。

next[2],字符串“ab”,前綴{a},后綴{b},沒有相等前后綴,next記為0。

next[3],字符串“aba”,前綴{a,ab},后綴{a,ba},相等前后綴{a},長度為1,next記為1。

next[4],字符串“abaa”,前綴{a,ab,aba},后綴{a,aa,baa},相等前后綴{a},長度為1,next記為1。

next[5],字符串“abaab”,前綴{a,ab,aba,abaa},后綴{b,ab,aab,baab},相等前后綴{ab},長度為2,next記為2。

next[6],字符串“abaabc”,前綴{a,ab,aba,abaa,abaab},后綴{c,bc,abc,aabc,baabc},相等前后綴{},next記為0。

next[7],字符串“abaabca”,前綴{a,ab,aba,abaa,abaab,abaabc},后綴{a,ca,bca,abca,aabca,baabca},相等前后綴{a},長度為1,next記為1。

next[8],字符串“abaabcac”,前綴{a,ab,aba,abaa,abaab,abaabc,abaabca},后綴{c,ac,cac,bcac,abcac,aabcac,baabcac},相等前后綴{},next記為0。

i12345678
str.charAt(i)abaabcac
next[i]00112010

由于使用next[]時,每次失配,都需要找它前面一個元素的next[]進行移動,為了方便,我們將next數組右移一位。最左側填充-1,舍棄最右側的元素。

i12345678
str.charAt(i)abaabcac
next[i]-10011201

為了簡化計算,我們對next[]整體+1,這里得到的是我們通常使用的next[]。

i12345678
str.charAt(i)abaabcac
next[i]01122312

?

求解next數組代碼:

private static int[] get_Next(String str){ int[] next = new int[str.length()+1]; int j = next[2];// 這里next[1]和next[2]直接賦值next[1] = 0;next[2] = 1;for(int i = 2; i < str.length(); i++) { while(j > 0 && str.charAt(i-1) != str.charAt(j)) {j = next[j]; }if(str.charAt(i-1) == str.charAt(j)) {j++;}next[i] = j;} return next; }

KMP算法改進--nextval[]

比較當前next[i]的值,與

1.前兩位必為0,1

計算nextval[3]時,我們可以知道第三位字符位‘a’,next[3]=1,故查看第1位的字符為‘a’,字符相同,所以nextval[3]=next[1]=0

計算nextval[4]時,我們可以知道第四位字符位‘a’,next[4]=2,故查看第2位的字符為‘b’,字符不同,所以nextval[4]=next[4]=2

計算nextval[5]時,我們可以知道第五位字符位‘b’,next[5]=2,故查看第2位的字符為‘b’,字符相同,我們知道next[2]=1,故繼續查看第1位的字符為‘a’,字符不同,所以nextval[5]=next[2]=1

計算nextval[6]時,我們可以知道第六位字符位‘c’,next[6]=3,故查看第3位的字符為‘a’,字符不同,所以nextval[6]=next[6]=3

計算nextval[7]時,我們可以知道第七位字符位‘a’,next[7]=1,故查看第1位的字符為‘a’,字符相同,所以nextval[7]=next[1]=0

計算nextval[8]時,我們可以知道第八位字符位‘c’,next[8]=2,故查看第2位的字符為‘b’,字符不同,所以nextval[7]=next[7]=2

i12345678
str.charAt(i)abaabcac
nextval[i]01021302

根據next數組,我們再來做一遍這個題目:給定字符串為abcabaaabaabcac,求其子串abaabcac在其中出現的位置。

?

1.創建匹配,第4個字符發生失配

2.使失配位與子串的第next[4]=2位相對,但是這是第二個字符又失配了

3.使失配位與子串的第next[2]=1位相對,此時第一個字符就失配

4.使失配位與子串的第next[1]=0位相對,注意我們的next數組是從1開始算的,所以相當于整體后移一個單位,下圖的失配位實際是"c"

5.使失配位與子串的第next[4]=2位相對

6.使失配位與子串的第next[4]=2位相對

7.匹配成功

完整代碼如下:

public class Main { public static void main(String[] args) { String str = "abaabcac"; String orig ="aabaabcac"; int[] next = get_Next(str); for (int i = 1; i < next.length; i++) {System.out.print(next[i] + " ");}System.out.println();search(orig, str, next); } //next[i]表示的是str的"部分匹配表",這個表表示的是str前綴與后綴的最長公共字符串的長度private static int[] get_Next(String str){ int[] next = new int[str.length()+1]; int j = next[2];// 這里next[1]和next[2]直接賦值next[1] = 0;next[2] = 1;// 第2位之后的next,為什么從2開始,不是已經賦值了嗎?這在于str.charAt(0)為字符串的第一個字母for(int i = 2; i < str.length(); i++) { while(j > 0 && str.charAt(i-1) != str.charAt(j)) {j = next[j]; }if(str.charAt(i-1) == str.charAt(j)) {j++;}next[i] = j;} return next; } //orig為主串,而find為模式串,查找匹配位置以及匹配長度 private static void search(String orig, String find, int[]next){ int j = next[0]; for(int i = 0;i < orig.length(); i++){ while(j > 0 && orig.charAt(i) != find.charAt(j)) j = next[j]; if(orig.charAt(i) == find.charAt(j)){ j++; }if(j == find.length()){ System.out.println("find at position " + (i - j+1)); System.out.println(orig.subSequence(i - j + 1, i + 1)); j = next[j];}}} }

當然還有一種BM算法效率比KMP算法還好。有興趣的讀者可以參考時空權衡在模式匹配算法中的應用(JAVA)--Horspool算法(簡化版BM算法)

nextval數組實際的數值是明顯要小于next數組的,nextval數組由于考慮到了移動到的位置的數與當前位置數的關系,可以減少移動的距離。

?

?

總結

以上是生活随笔為你收集整理的模式匹配算法----KMP算法以及next数组的解法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美大胆a| 欧美午夜大片 | 美女性生活视频 | 精品久久久久久久久久岛国gif | 亚洲国产网站 | 精品国产免费一区二区三区 | 色男人天堂av | 日本福利一区二区三区 | 一个色亚洲 | 精品少妇一区二区三区密爱 | 视频在线观看免费 | 国产在线一区二 | 欧美一区网站 | 成人h动漫精品一区二区 | 婷婷丁香一区二区三区 | 欧美不卡一二三 | 国产精品日日摸天天碰 | 日本黄a| 欧美色v | 男女在线观看视频 | 一区二区日韩国产 | 91成人久久| 国产美女明星三级做爰 | 激烈娇喘叫1v1高h糙汉 | 午夜片在线观看 | 综合色爱 | 超碰中文在线 | 台湾swag在线观看 | 亚洲一级片在线观看 | 精品无码一区二区三区免费 | 亚洲情se | 波多野结衣免费看 | 天天天天操| 亚洲深夜| 久久精品5 | 男生把女生困困的视频 | 91视频福利 | 黄视频国产 | 日本a v网站| a亚洲天堂 | 天天干天天谢 | 西野翔之公侵犯中文字幕 | 国产一区二区三区影院 | 播放灌醉水嫩大学生国内精品 | 又色又爽又黄gif动态图 | 欧美久草 | 国产精品久久..4399 | 丰满岳乱妇国产精品一区 | 久久亚洲AV成人无码一二三 | 亚洲免费观看高清在线观看 | 亚洲国产视频一区二区三区 | 九色在线观看视频 | 好吊色欧美一区二区三区视频 | 国产在线导航 | 四虎免费影视 | 成人午夜黄色 | 日本福利社| 亚洲精品中文字幕乱码无线 | 97超碰在线免费 | 国产亚洲制服欧洲高清一区 | 天堂√8在线中文 | 国产亚洲av片在线观看18女人 | 婷婷免费视频 | 男人天堂一区二区 | 久久精品国产亚洲av嫖农村妇女 | 亚洲精品乱码久久久久久按摩观 | 在线观看国产精品一区 | 国内av网站| 久久精品国产99久久不卡 | 亚洲大胆视频 | 一本加勒比hezyo黑人 | 亚洲国产免费看 | 欧美黄页| 精品久久久久久久久久久久久久久 | 女生高潮视频在线观看 | 麻豆视频在线 | 国产大片中文字幕在线观看 | www一区| 欧美亚洲精品一区 | 黄色一级视频 | 亚洲精品乱码久久 | 国产网站免费在线观看 | 天天干天天草 | 狠狠操网站 | 天天操妹子 | 国产 日韩 欧美 在线 | 污网站在线播放 | 一个人在线观看www软件 | 暖暖免费观看日本版 | 亚洲高清中文字幕 | 中文字幕精品一区二区三区精品 | 三级毛毛片 | 午夜在线成人 | 中文字幕一区二区三区四区视频 | aa片在线观看视频在线播放 | 国产精品秘| 日韩精品一区二区三区丰满 | 国产精品第2页 | 亚洲精品国产精 |