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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

朴素模式匹配算法和KMP匹配算法 详细

發(fā)布時(shí)間:2024/8/1 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 朴素模式匹配算法和KMP匹配算法 详细 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

樸素模式匹配算法和KMP匹配算法

一、樸素模式

假設(shè)我們要從主串S=”goodgoogle"中找到子串T=“google"的位置,步驟如下:

i表示主串的當(dāng)前位置下標(biāo),j表示子串的當(dāng)前位置下標(biāo),如上圖在第一輪比較(i=1開始)中j=4和i=4的位置不匹配,接下來(lái)就要指針回退,從i=2開始比較,如下:

如此反復(fù)直到比較到 i =(主串長(zhǎng)度-子串長(zhǎng)度+1)的位置或者 j = 子串的長(zhǎng)度 就退出比較循環(huán),上面的主串和子串在比較到i=5的位置就完全匹配了。

#include <stdio.h>int Index(const char S[], const char T[], int pos){int i = pos; //主串當(dāng)前下標(biāo)int j = 1; //子串當(dāng)前下標(biāo)//S[0]是主串的長(zhǎng)度,T[0]是子串的長(zhǎng)度while(i <= S[0] && j <= T[0]){//如果相等則繼續(xù)向下比較if(S[i] == T[j]) {++i;++j;//如果不等則指針回退}else{i = i - j + 2; //主串回退j = 1;}}//j>T[0]則說(shuō)明子串被完全匹配if( j > T[0]) return i - T[0];else return 0; }int main(){char S[] = {10, 'g', 'o', 'o', 'd', 'g', 'o', 'o','g', 'l', 'e'}; char T[] = {6, 'g', 'o', 'o', 'g', 'l', 'e'};int i = Index(S, T, 1);printf("%d\n", i);return 0; }

分析一下這種匹配算法最好的情況時(shí)間復(fù)雜度是O(m),即主串的前m個(gè)字符剛好與子串相等,最壞的情況是每次最后一個(gè)字符不匹配,時(shí)間復(fù)雜度是O(m*n) m是主串長(zhǎng)度n是子串的長(zhǎng)度。

樸素模式匹配算法時(shí)間復(fù)雜度分析如下:(n為主串長(zhǎng)度,m為模式串長(zhǎng)度)

時(shí)間復(fù)雜度:

最好情況
O(1) 一開始就匹配成功。

最壞情況
O((n-m+1)*m) 每次不成功的匹配都發(fā)生在模式串的最后一個(gè)字符。

平均情況
O(n+m) 根據(jù)等概率原則,平均是(n+m)/2次查找。

二、KMP算法

像二進(jìn)制這樣的多個(gè)0和1重復(fù)的字符串,上面的模式匹配需要挨個(gè)遍歷是非常慢的,KMP算法可以大大避免重復(fù)遍歷的情況。

下面我們來(lái)看看KMP算法的基本原理

如上,可以看到主串S和子串T在第一輪比較的時(shí)候,前面5個(gè)相等,只有i=6和j=6的位置不等。由于子串T中abcde這5個(gè)字符本身互不相等,可以知道子串T中a就不可能和j=2、3、4、5的位置的字符相等。所以可以直接跳到i=6的位置進(jìn)行比較。

再看上圖,如果子串T中存在重復(fù)的元素(比如j=1,2和j=4,5處的字符),按照上面的分析,我們可以直接跳到i=4的位置比較,但是我們已經(jīng)知道j=1,2和j=4,5相等,并且i=4,5和j=4,5相等,所以可以不用比較i=4,5和j=1,2。

KMP模式匹配算法就是為了不讓i指針回退,既然i值不回退,我們就要考慮變化j的值了。通過(guò)上面的觀察可以發(fā)現(xiàn),j值的變化與主串其實(shí)沒有什么關(guān)系,而是取決于子串T中是否有重復(fù)問(wèn)題。

我們把T串各個(gè)位置的j值的變化定義為一個(gè)數(shù)組next,那么next的長(zhǎng)度就是T串的長(zhǎng)度,可以得到下面函數(shù):

#include <stdio.h>void get_next(const char T[], int *next){int i,j;i = 1;j = 0;next[1] = 0;//T[0]是子串T的長(zhǎng)度while(i < T[0]){//T[i]表示后綴的單個(gè)字符//T[j]表示前綴的單個(gè)字符if( j==0 || T[i] == T[j]){++i;++j;next[i] = j;}else{j = next[j];}} }int Index_KMP(const char S[], const char T[], int pos){int i = pos;int j = 1;int next[255];get_next(T, next);while(i <= S[0] && j <= T[0]){//相對(duì)于樸素算法,增加了一個(gè)j==0的判斷if( j==0 || S[i] == T[j]){++i;++j;}else{//j回退到合適的位置,i的值不變j = next[j];}}if( j>T[0]){return i-T[0];}else{return 0;} } int main(){return 0; }

整個(gè)算法的時(shí)間復(fù)雜度為O(n+m)

總結(jié)

以上是生活随笔為你收集整理的朴素模式匹配算法和KMP匹配算法 详细的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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