BF算法(暴力匹配算法):
将目标串的第一个字符与模式串的第一个字符进行匹配。如果相等,则继续匹配下一个字符;如果不等,模式串回退到第一个字符再与目标串的第二个字符匹配(每次匹配错误,目标串移动一个,模式串从头开始)。
时间复杂度:O(M*N);
代码实现:
int BF(char *str1,char *str2)
{
assert(str1 != NULL && str2 != NULL);
if(str1 == NULL || str2 == NULL)
{
return -1;
}
int i = 0;
int j = 0;
while(str1[i] != '\0' && str2[j] != '\0')
{
if(str1[i] == str2[j])
{
i++;
j++;
}
else
{
i = i - j + 1; //匹配错误,目标串移动一个
j = 0; //模式串从头开始
}
}
if(str2[j] == '\0')
{
return i-j;
}
return -1;
}
实例分析:
设目标字符串S=‘aabaabaabaac',模式字符串P=‘aabaac';
算法分析:
对于第二、五次比配,S[1]与P[0]、S[4]与P[0]肯定匹配(第一、四次匹配已经匹配成功);
对于第三、六次比配,S[2]与P[1]、S[5]与P[0]肯定不匹配(第二、五次匹配已经匹配失败);
对算法优化:优化匹配错误模式串返回的位置,减少匹配次数。
KMP算法:
利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。
时间复杂度:O(m+n)。
代码:
void GetNext(char *str, int len,int *next)
{
if(len == 0)
{
return;
}
int i = 1;
int k = -1;
next[0] = -1;
if(len == 1)
{
return;
}
next[1] = ++k;
while(i <len-1)
{
if(k == -1 || str[i] == str[k])
{
i++;
k++;
next[i]=k;
}
else
{
k=next[k];
}
}
}
int KMP(char *str1, char *str2)
{
int len1 = 0;
int len2 = 0;
int i = 0;
int j = 0;
while(str1[++len1]);
while(str2[++len2]);
if(len1 == 0 || len2 == 0)
{
return 0;
}
int *next = (int *)malloc(sizeof(int)*len2);
GetNext(str2,len2,next);
while(i < len1 && j < len2)
{
if(j == -1 || str1[i] == str2[j])
{
i++;
j++;
}
else
{
j=next[j];
}
}
free(next);
if (j >= len2)
{
return i-j;
}
return -1;
}
实例分析:
设目标字符串S=‘aabaabaabaac',模式字符串P=‘aabaac';
next数组生成过程:
next数组的优化:
void GetNextVal(char *str, int len,int *next)
{
if(len == 0)
{
return;
}
int i = 1;
int k = -1;
next[0] = -1;
if(len == 1)
{
return;
}
next[1] = ++k;
while(i <len-1)
{
if(k == -1 || str[i] == str[k])
{
i++;
k++;
if(str[i] != str[k])
{
next[i]=k;
}
else
{
next[i]=next[k];
}
}
else
{
k=next[k];
}
}
}
模式串t=‘abcaabbcabcaabdab’ ,该模式串的 next[] = {0 1 1 1 2 2 1 1 1 2 3 4 5 6 7 1 2};优化nextval[]= {0 1 1 0 2 1 3 1 0 1 1 0 2 1 7 0 1};