Boyer-Moore字符串查找算法的实现
前段时间在园子里看到一篇讲Boyer-Moore算法原理的文章http://kb.cnblogs.com/page/176945/,写的很详细,于是在这里自己写个C语言的实现,权当是练手吧。
基本思路是每次从模式串的最右端开始匹配,如果后缀不匹配,模式串可以快速地后移,从而快速地匹配字符串。要用一个数组right[],来存储失配时模式串的移动步数。数组的大小是256,即扩展的ASCII码表大小(即256个字符)。若对应字符不存在于模式串中,则赋值-1,否则表示字符出现在模式串中,查找失配时,模式串向右移动的步数。应该还有优化的空间,暂时没想了。
分成两个文件,一个.h文件,一个.c文件。实现中,若匹配成功则返回第一次出现模式串的位置,若不匹配则返回模式串长度。
N: 被搜索的字符串长度。
M: 模式串长度。
strsearch.h :
1 #ifndef _STRSEARCH_H
2 #define _STRSEARCH_H
3
4
5 /***ASCII list length***/
6
7 #define ASCII_LIST_LENGTH 256
8
9 /* Interface */
10
11 extern int BMSearch(char *dest_str,char *pattern);
12
13
14 #endif
strsearch.c :
1 #include <stdio.h>
2 #include <string.h>
3 #include "strsearch.h"
4
5 #ifdef _cplusplus
6 extern "C"{
7 #endif
8
9 /*
10 ******Implementation of Boyer-Moore Algorithm******
11 *
12 * This function is to solve the string search ,and somhow we
13 * can find the position of pattern string in the dest string
14 * quickly.
15 *
16 * Copyright(c) 2013.9.6 xiaoh
17 * All rights reserved.
18 *
19 ***************************************************
20 */
21
22
23 /*
24 * This function is to build the jump step list for each
25 * charactor.
26 *
27 */
28
29 void BoyerMoore(char *pattern,int right[])
30 {
31 int M = strlen(pattern);
32
33 for(int c=0;c<ASCII_LIST_LENGTH;c++)
34 right[c] = -1;
35 for(int j=0;j<M;j++)
36 right[pattern[j]] = j;
37 }
38
39 /*
40 * Main function of Boyer-More Search Algorithm
41 *
42 */
43
44 int BMSearch(char *dest_str,char *pattern)
45 {
46 /*Array right: steps to move for the pattern string*/
47 int right[ASCII_LIST_LENGTH];
48
49 BoyerMoore(pattern,right);
50
51 int N = strlen(dest_str);
52 int M = strlen(pattern);
53
54 int skip; //number to jump
55 for(int i=0;i<=N-M;i+=skip)
56 {
57 skip = 0;
58 for(int j=M-1;j>=0;j--)
59 {
60 if(pattern[j]!=dest_str[j+i])
61 {
62 skip = j-right[dest_str[i+j]];//calculate the step to jump
63 if(skip<1)
64 skip = 1;
65 break;
66 }
67 }
68 if(skip == 0)
69 {
70 printf("Search finished successfully.\n");
71 return i;
72 }
73 }
74 printf("String cannot be found.\n");
75 return N;
76 }
77
78 #ifdef _cplusplus
79 }
80 #endif
查找的最好情况时间复杂度约为O(N/M)(其实是查找完,但不匹配情况),这里需要和O(M)比较下,如果M比较大的话N/M就比较小一些;在最坏情况下,需要比较N/M组,每组比较M次,所以时间复杂度为O(N)。其查找速度确实比KMP算法还要快。