日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發布時間:2025/3/11 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符串的模式匹配--BF算法KMP算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

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

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

經過以上對比,我們可以發現KMP算法的效率要比BF算法的效率高,接下來看一下代碼。
BF算法

BF算法思想

  • 在串 S 和串 T 中分別設比較的起始下標 i 和 j;
  • 循環直到 S 中所剩字符個數小于 T 的長度或 T 的所有字符均比較完
    2 .1如果 S[i] = T [j] ,則繼續比較 S 和 T 的下一個字符 ;
    2 .2 如果S[i] != T [j],將 i 和 j 回溯 ,準備下一趟比較 ;
  • 如果 T 中所有字符均比較完 , 則匹配成功 , 返回匹配的起始比較下標 ;
    否則 ,匹配失敗 ,返回 0;
  • int BF(String S, String T, int pos) {//pos是進行模式匹配的起始位置int i = 0;int j = 0;int start = 0;//子串的起始位置if (pos < 0 || (pos + T.length >= S.length)) {//起始位置小于0或者起始位置加上模式串的長度大于主串的長度,就不用進行匹配了printf("Irregular position.\n");} else {//進行匹配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的算法中需要用到一個next數組,該數組是用來確定失配后模式串循環變量j回溯的位置的。

    next數組的計算

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

    next數組的計算還有簡單的方法,上述使用最基礎的方法計算的,便于理解

    KMP算法思想

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

    //計算next的值 void getNext(String T, int next[]) {int i;//循環變量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;//主串的循環變量int j = 0;//模式串的循環變量while (i < S.length && j < T.length) {if (S.str[i] == T.str[j]) {//若主串和模式串的字符相同,都向后移一位i++;j++;} else {//若失配了,模式串的循環變量就要根據next數組回溯j = next[j];if (j == -1) {i++;j++;//j=-1時,j必須要加1,否則下標越界導致運行出錯}}}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

    此外還需要做一些準備工作

    #include <stdio.h>#define MAX_SIZE 100typedef struct {//定義一個字符串的結構體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函數測試一下

    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”
    運行結果:

    總結

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

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