BF算法:
即暴风(Brute Force)算法,是普通的模式匹配算法,它的思想就是将子串的第一个字符与母串的第一个字符进行匹配,若相等,则继续比较子串的第二个字符和母串的第二个字符;若不相等,则比较母串的第二个字符和子串的第一个字符,依次比较下去,知道得出最后的匹配结果。算是一种蛮力算法。
代码:
int BF(Str *s,Str *sub,int pos)
{
assert(sub != NULL && s != NULL);
if(pos < 0 || pos > s->length)
{
return -1;
}
int i = pos;
int j = 0;
while( i < s->length && j < sub->length)
{
if(s->elem[i] == sub->elem[j])
{
i++;
j++;
}
else
{
i = i -j + 1;
j = 0;
}
}
if(j >= sub->length)
{
return i -j;
}
else
{
return -1;
}
}
KMP算法:
相比较于BF 算法,KMP算法建立了一个子串的next数组,用来储存子串j回退的位置;
next 数组各值的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀。例如如果next [j] = k,代表j 之前的字符串中有最大长度为k 的相同前缀后缀。
此也意味着在某个字符失配时,该字符对应的next 值会告诉你下一步匹配中,模式串应该跳到哪个位置(跳到next [j] 的位置)。如果next [j] 等于0或-1,则跳到模式串的开头字符,若next [j] = k 且 k > 0,代表下次匹配跳到j 之前的某个字符,而不是跳到开头,且具体跳过了k 个字符。
KMP的next 数组相当于告诉我们:当模式串中的某个字符跟文本串中的某个字符匹配失配时,模式串下一步应该跳到哪个位置。如模式串中在j 处的字符跟文本串在i 处的字符匹配失配时,下一步用next [j] 处的字符继续跟文本串i 处的字符匹配,相当于模式串向右移动 j - next[j] 位。
代码:
void GetNext(int *next,char *sub)//获取子串的next值
{
int lensub=strlen(sub);//计算sub的长度
next[0]=-1;
next[1]=0;//已知前两项的next值为-1和0
int i=2;//第二项开始
int k=0;//从0开始
while(i<lensub)
{
if((k==-1)||sub[k]==sub[i-1])//假设条件
{
next[i]=k+1;
i++;
k++;
}
else
{
k=next[k];
}
}
}
int KMP(char *str,char *sub,int pos)
{
int lens=strlen(str);
int lenb=strlen(sub);//分别计算str和sub的长度
if(pos<0||pos>lens)
{
return -1;
}
int *next=(int *)malloc(sizeof(int)*lenb);
GetNext(next,sub);
assert(next!=NULL);
int i=pos;
int j=0;
while(i<lens&&j<lenb)//遍历循环
{
if(j==-1||str[i]==sub[j])
{
i++;
j++;
}
else
{
j=next[j];
}
}
free(next);
if(j>=lenb)
{
return i-j;//找到后 最后返回i-j的值
}
else
{
return -1;//否则 返回-1
}
}