基本介紹
- 中文名:bitap算法
- 外文名:Baeza-Yates–Gonnet
- 學科:計算機技術
精確匹配,模糊匹配,
精確匹配
完全通用的精確字元串搜尋的bitap算法在偽代碼中看起來像這樣:
algorithm bitap_search(text : string, pattern : string) returns string m := length(pattern) if m == 0 return text /* Initialize the bit array R. */ R := new array[m+1] of bit, initially all 0 R[0] = 1 for i = 0; i < length(text); i += 1: /* Update the bit array. */ for k = m; k >= 1; k -= 1: R[k] = R[k-1] & (text[i] == pattern[k-1]) if R[m]: return (text+i - m) + 1 return nil
Bitap在其自然映射到簡單的按位運算方面與其他眾所周知的字元串搜尋算法不同,如上述程式的以下修改。請注意,在此實現中,違反直覺,每個值為零的位表示匹配,值為1的每個位表示不匹配。可以使用0和1的直觀語義編寫相同的算法,但在這種情況下,我們必須在內部循環中引入另一條指令進行設定R |= 1。在這個實現中,我們利用左移一個值在右邊移動零的事實,這正是我們需要的行為。
模糊匹配
為了使用bitap算法執行模糊字元串搜尋,有必要將位陣列R擴展為第二維。我們現在有k個不同的數組R1 ..k,而不是讓單個數組R在文本的長度上發生變化。數組Ri保存模式前綴的表示,該前綴與當前字元串的任何後綴匹配,其中包含i或更少的錯誤。在這種情況下,“錯誤”可以是插入,刪除或替換;有關這些操作的更多信息,請參閱萊文斯坦距離。
下面的實現使用模糊比特算法執行模糊匹配(使用最多k個錯誤返回第一個匹配)。但是,它只注重換人,而不是插入或缺失的-換句話說,一個漢明距離的ķ。和以前一樣,0和1的語義與它們的直觀含義相反。
#include <stdlib.h> #include <string.h> #include <limits.h> const char *bitap_fuzzy_bitwise_search(const char *text, const char *pattern, int k) { const char *result = NULL; int m = strlen(pattern); unsigned long *R; unsigned long pattern_mask[CHAR_MAX+1]; int i, d; if (pattern[0] == '\0') return text; if (m > 31) return "The pattern is too long!"; /* Initialize the bit array R */ R = malloc((k+1) * sizeof *R); for (i=0; i <= k; ++i) R[i] = ~1; /* Initialize the pattern bitmasks */ for (i=0; i <= CHAR_MAX; ++i) pattern_mask[i] = ~0; for (i=0; i < m; ++i) pattern_mask[pattern[i]] &= ~(1UL << i); for (i=0; text[i] != '\0'; ++i) { /* Update the bit arrays */ unsigned long old_Rd1 = R[0]; R[0] |= pattern_mask[text[i]]; R[0] <<= 1; for (d=1; d <= k; ++d) { unsigned long tmp = R[d]; /* Substitution is all we care about */ R[d] = (old_Rd1 & (R[d] | pattern_mask[text[i]])) << 1; old_Rd1 = tmp; } if (0 == (R[k] & (1UL << m))) { result = (text+i - m) + 1; break; } } free(R); return result; }