这个算法的逻辑以前花时间傻傻看懂过,最近需要用,细节逻辑就懒得看了,觉得没必要。真需要自己设计逻辑时再烧脑吧。
KMP算法代码:
void Next(char* T,int* next){
int i=1;
next[1]=0;
int j=0;
while (i<strlen(T))
{
if(j==0||T[i-1]==T[j-1])
{
i++;j++;
if (T[i-1]!=T[j-1])
next[i]=j;
else
next[i]=next[j];
}
else
j=next[j];
}
}
int KMP(char *S,char *T) //S为大片字符串,T为寻找的字符串
{
int next[10];
Next(T,next);
int i=1,j=1;
while (i<=strlen(S)&&j<=strlen(T))
{
if(j==0||S[i-1]==T[j-1])
{
i++;j++;
}
else
j=next[j];
}
if(j>strlen(T))
return i-(int)strlen(T);
return -1;
}
相对于逐个字符偏移比较。
KMP的核心就是Next函数,用需要寻找个字符串(T)做标记。next数组对应T的每个字节记录标记。
标记意义为:若对应字节比较失败,以T的标记数的字节去比较
例如:S为"aaaab";T为"aab"。
普通算法逐个比较:到'b'失败了,再从T的第一个'a'对应S的第二个'a'比较,再第三个'a',最后'b'也成功就ok;数数比较字符的次数。一共9次比较成功。
KMP算法:先比较3次,'b'失败了,由于T的第一第二字节一样,所以三个字节失败,右移时,第一个字节不用比就知道对的,只要从第二个字节比就好了,再以此类推。所以next[2] = 2的话,记录下次第二个开始比较。这样一共比较7次就成功了。就优化了普通逐个比较的算法。
就是T中后面的字节或一些字节与前面重复会情况,可跳过一些可以确定的字节,具体细节逻辑,就不花时间玩了,知道它优化了什么就差不多了。
以上只找到第一个相同的字符串位置
/
做个修改找出所有字符串位置做个可以索引的数组,就满足项目需要了
vector<int> IndexGroup;
void KMPtoIndexing( const char* S,const char *T )
{
int next[30] = {0};
Next(T,next);
int i=1,j=1;
while(i< fileLen){
if(j==0||S[i-1]==T[j-1])
{
i++;
j++;
}
else
j=next[j];
if (j >= strlen(T))
{
IndexGroup.push_back(i-strlen(T)-1);
j = 0;
}
}
}