参考:https://blog.csdn.net/v_july_v/article/details/7041827(看懂这个博文基本就懂了)
问题引入:已经文本串S---“BBC ABCDAB ABCDABCDABDE”,模式串P---“ABCDABD”请找出P在S中出现的位置。(S[15])
也就是在字符串中找到子串第一次出现的位置。
朴素算法:
int ViolentMatch(char* s, char* p)
{
int sLen = strlen(s);
int pLen = strlen(p);
int i = 0;
int j = 0;
int res=0;
for(i=0;i<sLen-pLen;i++)
{
if(s[i]==p[0])
{
for(j=0;j<pLen;j++)
if(s[i+j]!=p[j])
break;
if(j==pLen)
{
res=1;
break;
}
}
}
if(res)
{
printf("find!%d\n",i);
return i;
}
else
printf("NO\n");
}
浅显易懂,S从0到尾-尾 逐个排查,一旦第一个字符匹配那就进如第二轮排查,也就是到P中从0到尾 如果完全一致那就找到了。
问题1:两重循环效率不高,复制读是两个字符串长度的乘积。
问题2:S字符串是非常严谨的一个一个来的。
++++++++++++++++++插播一个错误 不要看++++++++++
现在我写一个引子算法,它是有逻辑问题的,一起看下:
int KmpSearch(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s);
int pLen = strlen(p);
printf("strlens--%d strlenp--%d\n",sLen,pLen);
while (i < sLen && j < pLen)
{
if (s[i] == p[j])
{
i++;
j++;
}
else
{
i++;
j=0;
}
printf("%d---%d---\n",i,j);//发现问题!逻辑bug
}
if (j == pLen)
{
printf("find!%d\n",i-j);
return i - j;
}
else
{
printf("NOfind!\n");
return -1;
}
}
问题来了,效果是找不到!用一重循环没有覆盖完全!也就是else里面怎么写呢?
bug是前面匹配相等,然后一个字符不在相等,调到了else此时j可以清退回到0头部,而i呢?其实i很尴尬,第一你希望在不匹配的时候它可以++使得有机会进如到if,第二如这个bug你又希望此时i回到当初的地方+1
+++++++++++++++++++广告结束++++++++++++++++
KMP的做法是:两重循环改为1重!S字符串不要每次都+1,而是只许前进不许后退。比如上面的例子,
此时会失配!只许前进不许后退的意思是现在S不是想以前一样步进一步,(那样的话就是其实已经走到了空格现在退回到B)
KMP做法是S你就不动了,我动P。
这个P往右移动了4位,4是怎么来的?这就是理论了。
void GetNext(char* p,int next[])
{
int pLen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen - 1)
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
++k;
++j;
next[j] = k;
}
else
{
k = next[k];
}
}
}
-1 0 0 0 0 1 2
也就是P---“ABCDABD”第几个失配就是那个数
int KmpSearch2(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s);
int pLen = strlen(p);
while (i < sLen && j < pLen)
{
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == -1 || s[i] == p[j])
{
i++;
j++;
}
else
{
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = next[j];//-1 0 0 0 0 1 2
}
}
if (j == pLen)
printf("%d\n",i-j);
//return i - j;
else
//return -1;
printf("NO\n");
}
现在就是理论了 数组怎么来的