kmp算法的优化
2017-11-17 14:11
211 查看
下面我们来说一下代码的优化。大家先看图:
我们新设置了一个nextval数组,nextval[j]表示优化后的在j失配,它应该退回的位置。我们原来求解j回退位置k时,其实还是存在无用功。如果p[j]=p[k],而我们在j位置发生了失配,j回退到k的位置,结果它的字符和j一样,那就无意义啊,因为它肯定还是会失配的,只有不一样的时候,才有可能匹配成功。所以当p[j]=p[k]我们就需要继续转到k=next[k]的位置上,然后比较新的p[k]是否等于p[j]如果等于,我们就需要再继续走,直到退到的字符不等于p[j],或者退到无路可退,也就是k为-1了。我们再仔细思考一下如果p[k]=p[j],我们是不是可以直接让
nextval[j]=nextval[k],因为我们的思想是从低下标开始求对应nextval值,如果已经求到nextval[j]时,k位置对应的nextval值早就已经优化过了,它保证了如果在k发生失配,则它退回的位置要么对应的字符是不同的,要么就是-1,也就是无路可退了。如果p[j]和p[k]是不同的,那nextval[j]=k;
好,我们来看一下代码实现:
tatic void GetNext(const char*sub,int *next)
{
int lensub = strlen(sub);
next[0] = -1;
next[1] = 0;
int j = 1;//通过j求j+1的值
int k = 0;
while(j+1
{
if(k==-1 || sub[j]==sub[k])
{
next[++j] = ++k;
}
else
{
k = next[k];//
}
}
}
static void getnextval(const char*sub,int *next,int *nextval)
{
int lensub = strlen(sub);
nextval[0] = -1;
int j = 1;
int k ;
while(j
{
k=next[j];
if(sub[j]==sub[k])
{
nextval[j]=nextval[k];
}
else
{
nextval[j]=k;
}
j++;
}
}
//KMP 算法特点:i不回退,时间复杂度O(n+m)
int KMP(const char *str,const char *sub,int pos)//O(n+m)
{
if(pos < 0)
{
return -1;
}
int lenstr = strlen(str);
int lensub = strlen(sub);
int i = pos;
int j = 0;
int *next = (int *)malloc(lensub*sizeof(int));
GetNext(sub,next);
int *nextval=(int*)malloc(lensub*sizeof(int));
getnextval(sub,next,nextval);
while(i
{
if(j==-1 || (str[i]==sub[j]))
{
i++;
j++;
}
else//i不回退,j退到next[j](即k位置)
{
j = nextval[j];
}
}
free(next);
free(nextval);
if(j >= lensub)//找到了
{
return i-j;
}
else
{
return -1;
}
}
标红的位置是相对于kmp算法,它优化之后添加的代码。
下面我们来说一下代码的优化。大家先看图:
我们新设置了一个nextval数组,nextval[j]表示优化后的在j失配,它应该退回的位置。我们原来求解j回退位置k时,其实还是存在无用功。如果p[j]=p[k],而我们在j位置发生了失配,j回退到k的位置,结果它的字符和j一样,那就无意义啊,因为它肯定还是会失配的,只有不一样的时候,才有可能匹配成功。所以当p[j]=p[k]我们就需要继续转到k=next[k]的位置上,然后比较新的p[k]是否等于p[j]如果等于,我们就需要再继续走,直到退到的字符不等于p[j],或者退到无路可退,也就是k为-1了。我们再仔细思考一下如果p[k]=p[j],我们是不是可以直接让
nextval[j]=nextval[k],因为我们的思想是从低下标开始求对应nextval值,如果已经求到nextval[j]时,k位置对应的nextval值早就已经优化过了,它保证了如果在k发生失配,则它退回的位置要么对应的字符是不同的,要么就是-1,也就是无路可退了。如果p[j]和p[k]是不同的,那nextval[j]=k;
好,我们来看一下代码实现:
tatic void GetNext(const char*sub,int *next)
{
int lensub = strlen(sub);
next[0] = -1;
next[1] = 0;
int j = 1;//通过j求j+1的值
int k = 0;
while(j+1
{
if(k==-1 || sub[j]==sub[k])
{
next[++j] = ++k;
}
else
{
k = next[k];//
}
}
}
static void getnextval(const char*sub,int *next,int *nextval)
{
int lensub = strlen(sub);
nextval[0] = -1;
int j = 1;
int k ;
while(j
{
k=next[j];
if(sub[j]==sub[k])
{
nextval[j]=nextval[k];
}
else
{
nextval[j]=k;
}
j++;
}
}
//KMP 算法特点:i不回退,时间复杂度O(n+m)
int KMP(const char *str,const char *sub,int pos)//O(n+m)
{
if(pos < 0)
{
return -1;
}
int lenstr = strlen(str);
int lensub = strlen(sub);
int i = pos;
int j = 0;
int *next = (int *)malloc(lensub*sizeof(int));
GetNext(sub,next);
int *nextval=(int*)malloc(lensub*sizeof(int));
getnextval(sub,next,nextval);
while(i
{
if(j==-1 || (str[i]==sub[j]))
{
i++;
j++;
}
else//i不回退,j退到next[j](即k位置)
{
j = nextval[j];
}
}
free(next);
free(nextval);
if(j >= lensub)//找到了
{
return i-j;
}
else
{
return -1;
}
}
标红的位置是相对于kmp算法,它优化之后添加的代码。
相关文章推荐
- KMP算法的优化
- KMP算法理解,and优化(待发)
- C++实现KMP算法(优化版)
- KMP算法next数组计算方法的优化
- KMP算法及其优化算法
- 计算子串在主串中的位置及其优化(KMP算法)
- 前缀中的周期---非优化KMP算法的运用
- 根据算法思路自己实现了kmp算法(未优化)
- KMP算法及优化
- KMP算法(未优化版本,算法导论原版)
- KMP算法(待优化)--2015年7月25日14:04:25V1.0版
- KMP算法及优化
- KMP算法的正确性证明及一个小优化
- 经典算法之KMP算法及其优化
- KMP算法的Java实现(优化和非优化求next数组)
- KMP算法总结(纯算法,为优化,没有学应用)
- KMP算法之最终实现及优化 - 数据结构和算法39
- 基于网上流传的错误KMP算法优化代码的纠正
- KMP算法的一些误区及其优化
- KMP算法代码实现和优化(不太能理解具体的过程和该算法思想)