C语言实现
主函数及声明
#include <stdio.h>
#include <string.h>
//定长字符串存储的声明
#define MAXSIZE 255
typedef unsigned char SString [MAXSIZE+1];//0号位置存放字符串长度
//函数提前声明
int getStr(SString T1,SString T2);
void getNext(SString T,int next[]);
void strAssign(SString SS, char *s);
int strStr(char *haystack, char *needle);
int useNext(SString T1,SString T2,int next[]);
//主程序
void main()
{
char *s = "ababc";
char *sss="cccababcabcacddd";
int next [MAXSIZE];//next数组的0号位置不管
int i;
SString SS,SSS;
strAssign(SS,s);
strAssign(SSS,sss);
printf("主串 :%s\n",&SSS[1]);
printf("模式串 :%s\n",&SS[1]);
getNext(SS,next);
printf("next数组:");
for(i=1;i<=SS[0];i++)
printf("%d ",next[i]);
printf("\n匹配位置:%d\n",useNext(SSS,SS,next));
}
实现效果:
函数:字符串分配
void strAssign(SString SS,char *s)
{
int i , j;
for(i = 0;i<=MAXSIZE;++i)//清空S,下标从0到255
SS[i]='\0';
SS[0] = strlen(s);
for(j = 1;*s!='\0';++j)//填充S
SS[j] = *s++;
}
函数:暴力寻找子串
为了更好地理解KMP算法所提高的效率(以空间换时间),此函数为暴力寻找子串,即针对主串的每一个字符都在子串进行一次匹配,针对两种不同的字符串存储方式,给出两个不同参数的函数。
①定长顺序存储
声明:
typedef unsigned char SString [MAXSIZE+1];//0号位置存放字符串长度
函数:
int getStr(SString T1, SString T2)
{
int i = 1,j =1,k=i;
while(i<=T1[0]&&j<=T2[0])
{
if(T1[i]==T2[j])
{
++i;
++j;
}
else
{
j=1;
i=++k;
}
}
if(j>T2[0])
return k;
else
return -1;
}
②堆分配存储
int strStr(char *haystack, char *needle)
{
int m = strlen(haystack),n = strlen(needle);
int i,j;
for(i = 0;i+n<=m;++i)
{
int flag = 1;
for(j = 0;j<n;++j)
{
if(haystack[i+j]!=needle[j])
{
flag = 0;
break;
}
}
if(flag)
return i;
}
return -1;
}
函数:建立next数组
KMP算法分为建立next数组与使用next数组两个部分;
void getNext(SString T,int next[] )
{
int i = 1,j = 0; //声明两个指针一个前指针j一个后指针i
next[1]=0; //next数组1号位对应模式串第一个字符,即首位置零
while(i<T[0]) //遍历模式串,直到最后一个元素下标为T[0]-1
{
if(j==0||T[i]==T[j]) //首次或当字符相同时,两指针同时后移,并将i下标的next值设为j
{
++i;
++j;
next[i]=j;
}
else
j=next[j]; //当字符不同时,将前指针去找对应的next值;
}
}
函数:使用next数组
int useNext(SString T1,SString T2,int next[])
{
int i = 1,j=1;
while(i<=T1[0]&&j<=T2[0])
{
if(j==0||T1[i]==T2[j])
{
++i;
++j;
}
else
j=next[j];
}
if(j>T2[0])
return i-T2[0];
else
return 0;
}