串的朴素算法和KMP匹配算法
算法实现
//时间复杂度: O(n*m)
int BF(const char* s, const char* p, int pos)
{
int i = pos, j = 0;
int lens = strlen(s);
int lenp = strlen(p);
while (i < lens && j < lenp)
{
if (s[i] == p[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
}
if (j >= lenp)
{
return i - j;
}
return -1;
}
BF算法的思想:
BF算法的优点:容易理解,代码易实现
缺点:时间复杂度过大O(n*m)
KMP算法的实现:
void GetNext(int* next, const char* p)
{
int lenp = strlen(p);
if (lenp < 2)
{
next[0] = -1;
return;
}
next[0] = -1;
next[1] = 0;
int i = 1;
int k = 0;
while (i + 1 < lenp)// 利用
{
if (k == -1 || p[i] == p[k])
{
// next[i + 1] = k + 1;
// i++;
// k++;
next[++i] = ++k;
}
else
{
k = 0;
next[++i] = k;
/* k = next[k];*/
}
}
}
int KMP(const char* s, const char* p, int pos)
{
int i = pos;
int j = 0;
int lens = strlen(s);
int lenp = strlen(p);
int* next = (int*)malloc(sizeof(int) * lenp);
assert(next != NULL);
GetNext(next, p);
while (i < lens && j < lenp)
{
if (j == -1 || s[i] == p[j])
{
i++;
j++;
}
else
{
// i是不需要回退的
// j回退到其next数组指定的k位置
j = next[j];
}
}
free(next);
if (j >= lenp)
{
return i - j;
}
return -1;
}
KMP算法的思想
主串的i指针是否需要回退?
总结:
第一种情况下:i回退没有价值,所以不回退
第二种情况下:i回退虽然有价值,但是i回退这个操作可以让j替代,以避免让i回退
j回退到哪里?
说是回退到适当的位置k,那么k怎么求?
核心思想:模式串返回的适当位置通过调用函数输出为一个数组next。