字串核对
今日的一些高階程式語(yǔ)言對(duì)于字串的處理支援越來(lái)越強(qiáng)大(例如Java、Perl等),不過(guò)字串搜尋本身仍是個(gè)值得探討的課題,在這邊以Boyer- Moore法來(lái)說(shuō)明如何進(jìn)行字串說(shuō)明,這個(gè)方法快且原理簡(jiǎn)潔易懂。
解法字串搜尋本身不難,使用暴力法也可以求解,但如何快速搜尋字串就不簡(jiǎn)單了,傳統(tǒng)的字串搜尋是從關(guān)鍵字與字串的開(kāi)頭開(kāi)始比對(duì),例如 Knuth-Morris-Pratt 演算法?字串搜尋,這個(gè)方法也不錯(cuò),不過(guò)要花時(shí)間在公式計(jì)算上;Boyer-Moore字串核對(duì)改由關(guān)鍵字的后面開(kāi)始核對(duì)字串,并制作前進(jìn)表,如果比對(duì)不符合則依前進(jìn)表中的值前進(jìn)至下一個(gè)核對(duì)處,假設(shè)是p好了,然后比對(duì)字串中p-n+1至p的值是否與關(guān)鍵字相同。
如果關(guān)鍵字中有重復(fù)出現(xiàn)的字元,則前進(jìn)值就會(huì)有兩個(gè)以上的值,此時(shí)則取前進(jìn)值較小的值,如此就不會(huì)跳過(guò)可能的位置,例如texture這個(gè)關(guān)鍵字,t的前進(jìn)值應(yīng)該取后面的3而不是取前面的7。
#include <stdio.h> #include <stdlib.h> #include <string.h> void table(char*); // 建立前進(jìn)表 int search(int, char*, char*); // 搜尋關(guān)鍵字 void substring(char*, char*, int, int); // 取出子字串 int skip[256]; int main(void) { char str_input[80]; char str_key[80]; char tmp[80] = {'\0'}; int m, n, p; printf("請(qǐng)輸入字串:"); gets(str_input); printf("請(qǐng)輸入搜尋關(guān)鍵字:"); gets(str_key); m = strlen(str_input); // 計(jì)算字串長(zhǎng)度 n = strlen(str_key); table(str_key); p = search(n-1, str_input, str_key); while(p != -1) { substring(str_input, tmp, p, m); printf("%s\n", tmp); p = search(p+n+1, str_input, str_key); } printf("\n"); return 0; } void table(char *key) { int k, n; n = strlen(key); for(k = 0; k <= 255; k++) skip[k] = n; for(k = 0; k < n - 1; k++) skip[key[k]] = n - k - 1; } int search(int p, char* input, char* key) { int i, m, n; char tmp[80] = {'\0'}; m = strlen(input); n = strlen(key); while(p < m) { substring(input, tmp, p-n+1, p); if(!strcmp(tmp, key)) // 比較兩字串是否相同 return p-n+1; p += skip[input[p]]; } return -1; } void substring(char *text, char* tmp, int s, int e) { int i, j; for(i = s, j = 0; i <= e; i++, j++) mp[j] = text[i]; tmp[j] = '\0'; }?
總結(jié)