子串的查找
BF查找法 时间复杂度(o(n*m))
abbaaaabaab
I 判断条件: i与j相等 i++;j++;
aaba i != j
J i=i-j+1; j回退到开始
KMP算法 时间复杂度(o(n+m))
如果j 能自己回退到他该回退位置,i就不用回退,这样就大大提高了算法的时间复杂度
,next数组就刚好提供j的回退下标
Si-j.....Si-1 =P0....Pj-1 (1)
P0......Pk-1=Si-k...Si-1 (2)
Si-k.....Si-1=Pj-k....pj-1 (3)
由(2),(3)推出
P0.....Pk-1=Pj-k....pj-1 (4)
通过(4)的结论我知道了next的寻找方式
在匹配成功的子串中查找两个最长且相等的真子串,这两个真子串的要求如下:
一个以子串的开头作为开头,另一个以匹配成功的最后一个字符作为结尾。
a b c d a b c d a b a b c
-10 0 0 0 1 2 3 4 5 6 1 2
这就是next数组的寻找方式
Next数组算法思想:
a b c d a b c d a b a b c
K j
当arr[k]与arr[j]相等时j++;i++;
不相等时:k回退到原来
static int * GetNext(const char *sub) { int lensub = strlen(sub); int *next = (int *)malloc(lensub*sizeof(int)); assert(next != NULL); next[0] = -1; next[1] = 0; int j = 1; int k = 0; while(j+1<lensub) { if((k==-1) || (sub[k]==sub[j])) { /*next[j+1] = k+1; j++; k++;*/ next[++j] = ++k; } else { k = next[k];//*********** } } return next; } 找到next数组后,方法和BF相同就是i不回退就好了,j=next数组 int KMP(const char *str,const char *sub,int pos) {//O(n+m) assert(str!=NULL && sub!=NULL); int lenstr = strlen(str); int lensub = strlen(sub); if(pos<0 || pos>=lenstr) { return -1; } //int next[10] = {0};//todo int *next = GetNext(sub); int i = pos; int j = 0; while(i<lenstr && j<lensub) { if(j==-1 || (str[i]==sub[j])) { i++; j++; } else { //i不回退 j = next[j]; } } free(next); if(j >= lensub) { return i-j; } else { return -1; } }