一、查找字符串字串
-
BF算法
暴力匹配(BF)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较,直到得出最后的匹配结果。int BF(const char *str,const char *sub,int pos) { assert(str!=NULL&&sub!=NULL); int i=pos;//用i来记录S中字符的位置 int j=0;//用j来记录T中字符的位置 int lens=strlen(str); int lensub=strlen(sub); //当S不为空并且T不为空时,逐个进行字符的比较 while(j<lensub&&i<lens) { if(str[i]==sub[i]) //当S中第i个字符与T中第j个字符相等时,i向后移一个,j向后移一个 { i++; j++; } else //当S中第i个字符与T中第i个字符不相等时,i回到前一个位置的下一个位置,j回到0号位置 { i=i-j+1; j=0; } } if(j>=lensub) //当j走完T的长度时,也就说明T在S中匹配成功 { return i-j; //此时返回字串在主串中的下标位置,此时i在该返回下标位置+j的长度位置,所以返回i-j,本例中返回下标3 } //匹配失败,则返回-1,因为-1下标不存在,不能返回0下标 else return -1; }
关于BF算法:
- 当第一个字符不相同时j也会继续向后比较,比如例子中的“abcdefg”和“def”,当“a”和“d”不相同时,则明显之后的两个字符及时相等也不是相同的子串。
- 每次j下标都要回到0号下标,当主串和字串匹配失败时,主串进行回溯会影响效率,回溯之后,主串与字串有些部分比较是没有必要的
综上:
这种简单的丢弃前面的匹配信息的算法,造成了极大的浪费和底下的匹配效率
-
KMP算法
在KMP算法中,对于每一个模式串都会事先计算出模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数,这样就很好的解决了BF算法的缺陷
比如,当匹配失败后,最好是能够将模式字串尽量的右移和主串进行匹配,右移的距离在KMP算法中是这样计算的:在已经匹配的字串中,找到最长的相同的前缀和后缀,然后移动使他们重叠,这个位置就是j要回退的位置,这样j就不用每一次都回到0号位置了,每一次j回退的位置存储在一个数组里,称之为next数组
那么j回退的位置什么是最合适的呢
我们通过一组图来看一下:
根据以上理论,我们求得模式串的next数组:
代码实现:#include "stdio.h" /*********************** T: 9 a b a b a a a b a j: 0 1 2 3 4 5 6 7 8 9 k: 0 1 1 2 3 4 2 2 3 *************************/ typedef char *String; // i: 表示后缀 j: 前缀 前缀是固定的,后缀是相对的 void GetNext(String T, int *next) { int i = 1, j = 0; while (i < T[0]) { if (j == 0 || T[i] == T[j]) { i++; // 2 3 j++; // 1 0 if (T[i] != T[j]) { next[i] = j; //1 1 } else { next[i] = next[j]; } } else { j = next[j]; // 0 } } } int IndexKMP(String s, String T, int pos) { int i = pos; int j = 1; int next[255]; GetNext(T, next); while (i <= s[0] && j <= T[0]) { if (s[i] == T[j]) { i++; j++; } else { j = next[j]; } } if (j > T[0]) { return i-T[0]; } else { return 0; } } int main() { char str[255] = " abababaaaba"; char t[4] = " aba"; t[0] = 3; int next[255]; int i = 1; str[0] = 11; GetNext(str, next); for ( i = 1; i < 10; i++) { printf("%d ", next[i]); } printf("\n"); printf("%d", IndexKMP(str, t, 2)) ; return 0; }
二、问题