一.BF算法
时间复杂度为:O(m*n)
思想:假设现在主串S匹配到 i 位置,子串P匹配到 j 位置,则有:
如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i]! = P[j]),令i = i - j + 1,j = 0。相当于每次匹配失败时,i 回退到本次开始的下一个位置,j 回退到子串的开头。
算法实现:
int BF(const char *ps,const char *pstr,int pos)
{
if(ps == NULL || pstr == NULL)
{
return 0;
}
int pslen = strlen(ps);//注意:sizeof(ps)/sizeof(char)求下来为4,
cout<<pslen<<endl;
int pstrlen = strlen(pstr);//sizeof(pstr)/sizeof(char)
if(pos < 0 || pos > pslen)
{
return -1;
}
int i = pos;//ps的下标
int j = 0;//pstr的下标
while(i < pslen && j<pstrlen)
{
if(ps[i] == pstr[j])
{
i++;
j++;
}
else
{
i = i-j+1;//当匹配失败时i回到本次比较开始的下一次,j回到子串的头
j = 0;
}
}
if(j >= pstrlen)//如果if成立,则子串遍历完了,说明找到了子串
{
return i-j;
}
else
{
return -1;
}
}
二.KMP算法
时间复杂度:O(m+n)
思想:KMP算法中i不需要回退且j回退到next[j]的位置。具体思想以一张图来解释:
算法的实现:
int* Getnext(const char *sub)//此处的sub为遍历过str的前一部分
{
int len = strlen(sub);
assert(len >= 2);
int *next = (int*)malloc(len*sizeof(int));
next[0] = -1;//自己定
next[1] = 0;
int j = 1;
int k = 0;
while(j+1 < len)
{
if((k == -1) || (sub[k] == sub[j]))
{
next[++j] = ++k;//next[j+1] = k+1;j++;k++;
}
else
{
k = next[k];//////如果想求nextval只需要在此后加 if(sub[k]==sub[j]) { k=next[k];}
}
}
return next;
}
int KMP(const char *str,const char *sub,int pos)
{
int lens = strlen(str);
int lensub = strlen(sub);
if(pos <0 || pos >= lens)
{
return -1;
}
int i = pos;
int j = 0;
int *next = Getnext(sub);//获取next组
while(i < lens && j<lensub)
{
if((j == -1) || (str[i] == sub[j]))//第一个判断是因为开始的next[0]为-1
{
i++;
j++;
}
else
{
j = next[j];
}
}
free(next);
if(j >= lensub)
{
return i-j;
}
else
{
return -1;
}
}