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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

字符串的模式匹配--BF算法KMP算法

發(fā)布時(shí)間:2025/3/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符串的模式匹配--BF算法KMP算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

BF算法是基于主串指針回溯,重新與子串進(jìn)行逐字符進(jìn)行比較,主串為S什么要進(jìn)行回溯呢,原因在于模式P中存在相同的字符或者說由字符(串)存在重復(fù)(模式的部分匹配性質(zhì)),設(shè)想如果模式P中字符各不相同,主串就S的指針就根本不需要回溯;然而,我們可以發(fā)現(xiàn)在主串S與模式發(fā)生失配時(shí),主串指針進(jìn)行回溯會(huì)影響效率,因?yàn)橛捎谀J絊本身字符的部分部分匹配性質(zhì),回溯之后,主串S與模式T有些部分比較是沒有必要的,這就是對(duì)BF算法所要改進(jìn)的地方。

BF算法的執(zhí)行過程:
例:S =″aaaaaaaaaaab″
T =″aaab″

KMP算法的執(zhí)行過程:
例:S =″ababcabcacbab″
T =″abcac″

經(jīng)過以上對(duì)比,我們可以發(fā)現(xiàn)KMP算法的效率要比BF算法的效率高,接下來看一下代碼。
BF算法

BF算法思想

  • 在串 S 和串 T 中分別設(shè)比較的起始下標(biāo) i 和 j;
  • 循環(huán)直到 S 中所剩字符個(gè)數(shù)小于 T 的長度或 T 的所有字符均比較完
    2 .1如果 S[i] = T [j] ,則繼續(xù)比較 S 和 T 的下一個(gè)字符 ;
    2 .2 如果S[i] != T [j],將 i 和 j 回溯 ,準(zhǔn)備下一趟比較 ;
  • 如果 T 中所有字符均比較完 , 則匹配成功 , 返回匹配的起始比較下標(biāo) ;
    否則 ,匹配失敗 ,返回 0;
  • int BF(String S, String T, int pos) {//pos是進(jìn)行模式匹配的起始位置int i = 0;int j = 0;int start = 0;//子串的起始位置if (pos < 0 || (pos + T.length >= S.length)) {//起始位置小于0或者起始位置加上模式串的長度大于主串的長度,就不用進(jìn)行匹配了printf("Irregular position.\n");} else {//進(jìn)行匹配i = pos - 1;while (i < S.length && j < T.length) {if (S.str[i] == T.str[j]) {if (j == 0) {start = i;//記錄子串的起始位置}i++;j++;} else {//若前面的字符都不同,tag一直為0,所以必須分情況討論if (j != 0) {i = start + 1;} else {i = i + 1;}j = 0;}}if (j == T.length) {printf("ok\n");printf("start position = %d\n", start + 1);} else {printf("bu ok\n");}}return (start + 1);//返回子串的起始位置的邏輯位置 }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    KMP算法
    KMP的算法中需要用到一個(gè)next數(shù)組,該數(shù)組是用來確定失配后模式串循環(huán)變量j回溯的位置的。

    next數(shù)組的計(jì)算

    在“aba”中,前綴是真前綴的所有子串的集合,包括“a”、“ab”,除去最后一個(gè)字符的剩余字符串叫做真前綴在“aba”中,真前綴“ab”。同理,真后綴就是除去第一個(gè)字符的后面全部的字符串。
    next就是前綴和后綴中相同的子串的最大長度
    例如:
    1. 在“aba”中,前綴是“a”,后綴是“a”,那么兩者相同子串最長的就是“a”,相同的子串的最的長度就是1;
    2. 在“ababa”中,前綴是“aba”,后綴是“aba”,二者相同子串最長的是“aba”,相同的子串的最的長度就是3;
    3. 在“abcabcdabc”中,前綴是“abc”,后綴是“abc”,二者相同子串最長的是“abc”,相同的子串的最的長度就是3;
    這里有一點(diǎn)要注意,前綴必須要從頭開始算,后綴要從最后一個(gè)數(shù)開始算,中間截一段相同字符串是不行的

    next數(shù)組的計(jì)算還有簡單的方法,上述使用最基礎(chǔ)的方法計(jì)算的,便于理解

    KMP算法思想

  • 在串 S 和串 T 中分別設(shè)比較的起始下標(biāo) i 和 j;
  • 循環(huán)直到 S 中所剩字符長度小于 T 的長度或 T 中所有字符均比較完畢
    2 .1 如果 S[i] = T [j],則繼續(xù)比較 S 和 T 的下一個(gè)字符 ;
    2 .2 如果S[i] != T [j],將 j 向右滑動(dòng)到 next[ j] 位置 ,即 j = next[j] ;
    2 .3 如果 j = 0 ,則將 i 和 j 分別加 1 ,準(zhǔn)備下一趟比較;
  • 如果 T 中所有字符均比較完畢 , 則返回匹配的起始下標(biāo) ,否則返回 0;
  • 此處next數(shù)組使用一種簡單的方法計(jì)算的,此處就不過多解釋了,可以去網(wǎng)上學(xué)習(xí)一下,網(wǎng)上資源很多

    //計(jì)算next的值 void getNext(String T, int next[]) {int i;//循環(huán)變量int k;next[0] = -1;for (i = 1; T.str[i] != '\0'; ++i) {k = next[i - 1];while (k != -1) {if (T.str[i - 1] == T.str[k]) {next[i] = k + 1;break;} else {k = next[k];}}if (k == -1) {next[i] = 0;}} }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    KMP算法的匹配

    int KMP(String S, String T, int next[]) {int start = 0;int i = 0;//主串的循環(huán)變量int j = 0;//模式串的循環(huán)變量while (i < S.length && j < T.length) {if (S.str[i] == T.str[j]) {//若主串和模式串的字符相同,都向后移一位i++;j++;} else {//若失配了,模式串的循環(huán)變量就要根據(jù)next數(shù)組回溯j = next[j];if (j == -1) {i++;j++;//j=-1時(shí),j必須要加1,否則下標(biāo)越界導(dǎo)致運(yùn)行出錯(cuò)}}}if (j == T.length) {//判斷匹配是否成功start = i - T.length + 1;return start;}return -1; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    此外還需要做一些準(zhǔn)備工作

    #include <stdio.h>#define MAX_SIZE 100typedef struct {//定義一個(gè)字符串的結(jié)構(gòu)體char str[MAX_SIZE];int length;//字符串的長度 } String;//初始化 int initString(String *S) {S->length = 0;return 1; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    用main函數(shù)測試一下

    int main() {String S;//主串String T;//模式串initString(&S);//初始化initString(&T);createStr(&S);//從輸入字符串createStr(&T);printf("----------BF&KMP----------\n");BF(S, T, 0);printf("----------KMP----------\n");int next[T.length];getNext(T, next);for (int i = 0; i < T.length; ++i) {printf("next[%d] = %d\t", i, next[i]);}printf("\n");int start = KMP(S, T, next);printf("\nstart position = %d\n", start);return 0; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    例:
    S = “ababcabccabcacbab”
    T = “abcac”
    運(yùn)行結(jié)果:

    總結(jié)

    以上是生活随笔為你收集整理的字符串的模式匹配--BF算法KMP算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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