//KMP算法在我看来关键在于求next数组以及利用next数组来做匹配;
//或者说怎么样才能让匹配串能够跳跃的匹配进而减少时间,这就需要用到Next数组;
//还要知道next数组存储的是什么?next数组存储的是 匹配串的下标:理解一下就是在不匹配的时候:: j=next[i],,
//next数组的含义代表当前字符之前的字符串的最大公共前后缀;
//当不匹配时j的next值会告诉你下一步j会在哪个位置;
//想等的时候两个串的指针同时向下移动
//*但是如果不相等就需要用到next数组*//
//首先我们应该知道的是在匹配串p中的每一个位置都有可能与原串不匹配。
//那么如何来寻找这个next数组呢?一般是后面的next值是根据前面的next值求出来的;
//我们还可以知道,next数组的第一个和第二个一定是 -1 和 0;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i=0,j=0,k=-1;
int m=0;
int next[999]={0};
int cun[999];
int sum=0,sum1=0;
char t[999]={'a','b','a','b','s','d','a','b','a','b','h','i'};
char p[123]={'a','b','a','b'};
next[0]=-1;
// 这串求模式串的长度;
while(1)
{
if(p[m]>='a'&&p[m]<='z')
{
sum++;
m++;
}
else
break;
}
printf("匹配串长度:%d\n",sum);
// 这组代码求得是 文本串的长度
m=0;
while(1)
{
if(t[m]>='a'&&t[m]<='z')
{
sum1++;
m++;
}
else
break;
}
printf("%文本串长度:d\n",sum1);
// j循环只需要到倒数第二个就可以了,因为第 j+1 个 next数组的值是由 第 j 个数组的值求出来的;
// 而且我们知道next数组的第一个和第二个的值是固定的;
while(j<sum-1)
{
if(k==-1||p[j]==p[k]){
j++;
k++;
next[j]=k;
}
else{
k=next[k];
}
}
printf("next数组:");
for(i=0;i<=sum-1;i++)
printf("%d ",next[i]);
printf("\n");
// 下面来利用 next 数组,这里和BF算法差不多,相同就全下移,
//不同就采用next数组,这也是next数组被发明的原因
i=0,j=0;
m=0;
//当模式串和文本串的第一个的字符不一样那么就会执行 else ,将 j=-1;
//然后,进入if语句 将 i加1,j加1。此时的情况是 查看 模式串的第一个和文本串的第二个是否匹配
// 。。。如果还是不匹配 那么 j 还将变成-1 ,会再次进入 if语句 使 j加1,i加1;
// 。。。再次检查模式串的第一个和文本串的第三个是否匹配;
//如此周而复始,直到找到文本串中一个字符与模式串第一个字符相同
// //原来的一种写法使当 指针到达 各个串的末尾的时候 会 推出循环 :
// 退出循环我认为只有两种情况 :第一种就是 模式串指针到达最后并且越界这说明找到一个匹配的地方
// 第二种情况就是 文本串到达最后没找到一个字符与模式串的字符相同(此时文本串的指针会一直向后移动知道文本串越界)
// 还有就是 文本串指针正常移动::也会造成文本串数组越界。
//假设:我们知道 可以匹配但是不知道有几处。这样的话,一定会推出循环然后输出 匹配的位置;
//但是 现在我想 如果 文本串中有若干处 能够匹配的地方 我想将他们的位置都找出来,该怎么办呢???
while(i<sum1)
{
if(j==sum)
{
cun[m]=i-j;
m++;
i++;
j=0;
}
if(j==-1||t[i]==p[j])
{
i++;
j++;
}
else
{
j=next[j];
}
}
for(i=0;i<m;i++)
printf("%d ",cun[i]);
return 0;
}
最后附上两个大佬的博文 ,我向他们和其他的老师学习,为了帮助其他人,附上两位老师的代码,并再次致以崇高的敬意,如果有什么不当之处或有侵权现象,请与我联系。
https://blog.csdn.net/v_july_v/article/details/7041827#