标签:
BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。
BF算法实现:
1 int BF(char S[],char T[],int pos) 2 {//c从第pos位开始搜索匹配 3 int i=pos,j=0; 4 while(S[i+j]!=‘\0‘&&T[j]!=‘\0‘) 5 { 6 if(S[i+j]==T[j]) 7 j++; 8 else 9 { 10 i++; 11 j=0; 12 } 13 } 14 if(T[j]==‘\0‘) 15 return i+1; 16 else 17 return -1; 18 }
BF算法比较直接,是一种蛮力算法,该算法最坏情况下要进行M*(N-M+1)次比较,时间复杂度为O(M*N),下面来看一个效率非常高的字符串匹配算法,即KMP算法。
KMP算法又称“看毛片”算法,它完成的任务是:给定两个字符串S和T,长度分别为n和m,判断f是否在S中出现,如果出现则返回出现的位置。常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(nm)。kmp算法通过一个O(m)的预处理,使匹配的复杂度降为O(n+m)。
KMP算法思想:
优化的地方:如果我们知道模式中a和后面的是不相等的,那么第一次比较后,发现后面的的4个字符均对应相等,可见a下次匹配的位置可以直接定位到f了。说明主串对应位置i的回溯是不必要的。这是kmp最基本最关键的思想和目标。
由于abc 与后面的abc相等,可以直接得到红色的部分。而且根据前一次比较的结果,abc就不需要比较了,现在只需从f-a处开始比较即可。说明主串对应位置i的回溯是不必要的。要变化的是模式串中j的位置(j不一定是从1开始的,比如第二个例子)j的变化取决于模式串的前后缀的相似度,例2中abc和abc(靠近x的),前缀为abc,j=4开始执行。
下面我们来看看Next()数组:
void getNext(const char* pattern,int next[]) { next[0]= -1; int k=-1,j=0; while(pattern[j] != ‘\0‘) { if(k!= -1 && pattern[k]!= pattern[j] ) k=next[k]; ++j;++k; if(pattern[k]== pattern[j]) next[j]=next[k]; else next[j]=k; } }
Next()数组求出后,就可以进行字符串匹配了
int KMP(char *s,char* t) { if( !s||!t|| t[0]==‘\0‘ || s[0]==‘\0‘ ) return -1;//空指针或空串,返回-1。 int len=0; const char * c=t; while(*c++!=‘\0‘) { ++len; } int *next=new int[len+1]; getNext(t,next); int index=0,i=0,j=0; while(s[i]!=‘\0‘ && t[j]!=‘\0‘ ) { if(s[i]== t[j]) { ++i; ++j; } else { index += j-next[j]; if(next[j]!=-1) j=next[j]; else { j=0; ++i; } } } delete []next; if(t[j]==‘\0‘) return index; else return -1; }
写到这,KMP算法介绍的也差不多了,关于KMP算法优化,待续。。。。
标签:
原文地址:http://www.cnblogs.com/czx1/p/20141313707-cm.html