/** \brief KMP模式匹配
*
* \param
* \param
* \return
*
*/
#include <stdio.h>
#include <stdlib.h>
/***************************************************
*如果START_INDEX为1,则表示:本程序中字符数组从1号元素开始存储字符,0号元素存储字符的长度
*如果START_INDEX为0,则表示:本程序中字符数组从0号元素开始存储字符,数组以'\0'结尾
***************************************************/
#define START_INDEX 0 //0 or 1
#if START_INDEX==0
#define CHAR_NUM 1000 //最大支持CHAR_NUM个字符
#endif // START_INDEX
#if START_INDEX==1
/***************************************************
*如果当前元素的前K个字符与模式串中最靠近当前元素 *
*的K个字符字串完全相同那么当前元素的next值就是K+1*
***************************************************/
int get_next(char *Tstring,int *next)
{
int i=1,j=0; //j指向字串中当前比对到的元素,其本质是下标
next[1]=0; //规定第一个元素的next值为0
while(i<(Tstring[0]-0x30))
{
if(j==0||Tstring[i]==Tstring[j]) //如果当前的元素与上述注释中提到的字串后一个字符也匹配
{
next[++i]=j+1;//此时,上述注释中的字串元素个数K增加1,i加1(向后一个字符检索),而当前next值等于字串最后一个字符的next值加1
j++;//字串向后一个字符检索
}
else //如果不等
{
j=next[j]; //j指向字串中当前元素的next值指向的字符(字串的字串)
}
/*另一种写法
if(j==0||Tstring[i]==Tstring[j])
{
j++;
i++;
next[i]=j;
}
else
j=next[j];
*/
}
}
/*********************************************
*先计算模式串的next数组
*如果比对成功则继续比较
*如果比对失败模式串则滑动到next[j]处继续
**与主串当前元素比较
*********************************************/
int KMP(char *s,char *t)
{
int i=1,j=1;
int *next=(int *)malloc((t[0]-0x30+1)*sizeof(int));
get_next(t,next);
puts("比对顺序依次为:\n");
while(i<=s[0]&&j<=(t[0]-0x30))
{
if(j==0||s[i]==t[j])
{
printf("%d\t%d\n",i,j);
i++;
j++;
}
else
j=next[j];
}
free(next);
if(--j==(t[0]-0x30))
return i-j;
else
return -1;
}
int main()
{
int i,index;
char *t="8ababdabc";
char s[]={17,'d','v','h','v','b','a','b','a','b','d','a','b','c','a','s','x','z'};
index=KMP(s,t);
printf("\n%d\n",index);
return 0;
}
#endif // START_INDEX
#if START_INDEX==0
int get_next(char *Tstring,int *next)
{
int i=0,j=-1;
next[0]=-1;
while(Tstring[i]!='\0')
{
//if(j==-1||Tstring[i]==Tstring[j])
if(j==-1)
{
i++;
j++;
next[i]=j;
}
else
{
if(Tstring[i]==Tstring[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
return 0;
}
int KMP(char *s,char *t)
{
int i=0,j=0;
int next[CHAR_NUM];
get_next(t,next);
/*int m=0;
while(t[m]!='\0')
printf("%d\t",next[m++]);*/
puts("比对顺序:\n");
while(s[i]!='\0')
{
if(j>=0&&t[j]=='\0')//next[0]=-1,所以j==-1的情况是存在的
break;
if(j==-1||s[i]==t[j])
{
i++;
j++;
printf("%d\t%d\n",i,j);
}
else
{
j=next[j];
//printf("hello world!\n");
}
}
if(t[j]=='\0')
return i-j+1;
return -1;
}
int main()
{
int i,index;
char *t="ababdabc";
char s[]={'d','v','h','v','b','a','b','a','b','d','a','b','c','a','s','x','z','\0'};
index=KMP(s,t);
printf("\n%d\n",index);
return 0;
}
#endif // START_INDEX