1. 程式人生 > >模式匹配算法

模式匹配算法

assign wan 位置 有效 -c 描述 aps one 之前

1、基本概念:

  目標串:s

  模式串:t

  模式串第 j 個元素 :t[j]

2、BF算法:

  通過將目標串S的第一個字符與模式串T的第一個字符進行匹配,若相等,則繼續比較S的第二個字符和 T的第二個字符;若不相等,則比較S的第二個字符和T的第一個字符,依次比較下去,直到得出最後的匹配結果。BF算法是一種蠻力算法。

3、KMP算法:

  通過利用已經部分匹配這個有效信息,保證 i 指針不回溯,通過修改 j 指針,讓模式串盡量移動到有效位置。其中這個有效信息指的就是 next 數組和 nextval 數組。

3.1 next 數組手工求法

文字描述:

  這裏規定 next[0] = -1 ;

  對於 next[j] ,考慮 j 之前的串,找出前綴和後綴相同的最長字串,設長度為 k ,則 next[j] = k 。

實例:

  模式串 t : abcaba

  比如求 next[5] ,考慮 abcab ,易知前綴和後綴相同的最長字串為 ab ,其長度為 2 ,故 next[5] = 2 。

3.2 nextval 數組手工求法

文字描述:

  這裏同樣規定 nextval[0] = -1;

  若 t[j] = t[next[j]] ,則 nextval[j] = nextval[next[j]] ,否則保持不變。

實例:

j 0 1 2 3 4 5 6
模式 t a b c a b a a
next[j] -1 0 0 0 1 2 1
nextval[j] -1 0 0 -1 0 2 1

  比如求 nextval[4] ,首先 t[4] = b = t[next[4]] = t[1] ,則 nextval[4] = nextval[next[4]] = nextval[1] = 0 ;

  求 nextval[5] ,首先 t[5] = a =\= c = t[next[5]] = t[2] ,則 nextval[5] = next[5] = 2 。

4、完整代碼及運行結果

  苦逼的代碼:

技術分享圖片
  1 #include<stdio.h>
  2
#include <string.h> 3 #define MaxSize 50 4 typedef char ElemType; 5 6 typedef struct { 7 ElemType data[MaxSize]; 8 int length; 9 } SqString; 10 11 //BF 算法 12 int BFIndex(SqString s, SqString t) { 13 int i = 0, j = 0; 14 while(i < s.length && j < t.length) { 15 if (s.data[i] == t.data[j]) { 16 i++; 17 j++; 18 } else { 19 //目標串 s 指針 i 和模式串 t 指針 j 同步後移 20 i = i - j + 1; 21 j = 0; 22 } 23 } 24 if (j >= t.length) { 25 return i - t.length; 26 } else { 27 return -1; 28 } 29 } 30 31 //計算 next 數組 32 void GetNext(SqString t, int next[]) { 33 int j = 0, k = -1; 34 next[0] = -1; 35 while(j < t.length) { 36 if (k == -1 || t.data[j] == t.data[k]) { 37 j++; 38 k++; 39 next[j] = k; 40 } else { 41 k = next[k]; 42 } 43 } 44 } 45 //依據 next 數組實現的 KMP 算法 46 int KMPIndex(SqString s, SqString t) { 47 int i = 0, j = 0; 48 int next[MaxSize]; 49 GetNext(t, next); 50 while(i < s.length && j < t.length) { 51 if (j == -1 || s.data[i] == t.data[j]) { 52 i++; 53 j++; 54 } else { 55 //模式串 t 指針 j 後移 56 j = next[j]; 57 } 58 } 59 if (j >= t.length) { 60 //返回模式串 t 所在位置物理下標 61 return i - t.length; 62 } else { 63 //匹配失敗返回 -1 64 return -1; 65 } 66 } 67 68 //計算 nextval 數組 69 void GetNextval(SqString t, int nextval[]) { 70 int j = 0, k = -1; 71 nextval[0] = -1; 72 while(j < t.length) { 73 if (k == -1 || t.data[j] == t.data[k]) { 74 j++; 75 k++; 76 if (t.data[j] != t.data[k]) { 77 nextval[j] = k; 78 } else { 79 nextval[j] = nextval[k]; 80 } 81 } else { 82 k = nextval[k]; 83 } 84 } 85 } 86 //根據 nextval 數組實現的 KMP 算法 87 int KMPIndex1(SqString s, SqString t) { 88 int i = 0, j = 0; 89 int nextval[MaxSize]; 90 GetNextval(t, nextval); 91 while(i < s.length && j < t.length) { 92 if (j == -1 || s.data[i] == t.data[j]) { 93 i++; 94 j++; 95 } else { 96 //模式串 t 指針 j 後移 97 j = nextval[j]; 98 } 99 } 100 if (j >= t.length) { 101 //返回模式串 t 所在位置物理下標 102 return i - t.length; 103 } else { 104 //匹配失敗返回 -1 105 return -1; 106 } 107 } 108 109 //將字符串數組賦值給 SqString 類型的字符串 110 void StrAssign(SqString &s, char csrt[]) { 111 int i; 112 for (i = 0; csrt[i] != \0; i++) { 113 s.data[i] = csrt[i]; 114 } 115 s.length = i; 116 } 117 118 int main(int argc, char const *argv[]) { 119 SqString s, t; 120 StrAssign(s, (char *)"awzabcabaawanghizhi"); 121 StrAssign(t, (char *)"abcabaa"); 122 123 int next[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 124 int nextval[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 125 GetNext(t, next); 126 GetNextval(t, nextval); 127 128 printf("next and nextval:\n"); 129 printf("j\t\t"); 130 for (int i = 0; i < t.length; ++i) { 131 printf("%d\t", i); 132 } 133 printf("\nt[j]\t\t"); 134 for (int i = 0; i < t.length; ++i) { 135 printf("%c\t", t.data[i]); 136 } 137 printf("\nnext[j]\t\t"); 138 for (int i = 0; i < t.length; ++i) { 139 printf("%d\t", next[i]); 140 } 141 printf("\nnextval[j]\t"); 142 for (int i = 0; i < t.length; ++i) { 143 printf("%d\t", nextval[i]); 144 } 145 printf("\n\n"); 146 147 printf("BFIndex = %d\n", BFIndex(s, t)); 148 printf("KMPIndex = %d\n", KMPIndex(s, t)); 149 printf("KMPIndex1 = %d\n", KMPIndex1(s, t)); 150 return 0; 151 }
看著我的笑臉*^_^*,點一下塞~

  運行結果:

next and nextval:
j               0       1       2       3       4       5       6
t[j]            a       b       c       a       b       a       a
next[j]         -1      0       0       0       1       2       1
nextval[j]      -1      0       0       -1      0       2       1

BFIndex = 3
KMPIndex = 3
KMPIndex1 = 3

5、總結

  花費了我兩天中部分時間整理了模式匹配,只能算是初步掌握了這些,遠達不到應用的地步。。。

  之後的時間可能會整理一些應用樣例。。。

模式匹配算法