#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXLEN 255 //串的最大长度
#define CHUNKSIZE 80 //可由用户定义的块大小
//串的定长顺序存储结构
typedef struct
{
char ch[MAXLEN+1]; //存储串的一维数组
int length; //串的当前长度
}SString;
/*//串的堆式顺序存储结构
typedef struct
{
char *ch; //若是非空串,则按串长分配存储区否则ch为NULL
int length; //串的当前长度
}HString;
//串的链式存储结构
typedef struct Chunk
{
char *ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct
{
Chunk *head,*tail; //串的头和尾指针
int length; //串的当前长度
}LString;
//计算next函数值
void get_next(SString T,int next[])
{//求模式串T的next函数值并存入数组next
int i=1,j=0;
next[1]=0;
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
++i;
++j; //继续比较后继字符
next[i]=j;
}
else j=next[j]; //模式串向右移动
}
}*/
//计算next函数修正值
void get_nextval(SString T,int nextval[])
{//求模式串T的next函数修正值并存入数组nextval
int i=1,j=0;
nextval[1]=0;
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
++i;
++j; //继续比较后继字符
if(T.ch[i]!=T.ch[j]) nextval[i]=j;
}
else j=nextval[j]; //模式串向右移动
}
}
//BF算法
/*int Index_BF(SString S,SString T,int pos) //返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回为0
{ //其中,T非空1<=pos<=S.length
int i=pos;
int j=1; //初始化
while(i<=S.length && j<=T.length) //两个串均未比较到串尾
{
if(S.ch[i]==T.ch[j])
{
++i;
++j; //继续比较后继字符
}
else
{
i=i-j+2;
j=1; //指针后退重新开始匹配
}
}
if(j>T.length) return i-T.length; //匹配成功
else return 0; //匹配失败
}
*/
//KMP算法
int Index_KMP(SString S,SString T,int pos)
{ //利用模式串T的next函数在主串S中第pos个字符之后的位置
//其中,T非空,1<=pos<=S.length
int i=pos;
int j=1;
int nextval[255]; //定义next数组
get_nextval(T,nextval); //对串T进行分析,得到next数组
while(i<=S.length && j<=S.length) //两个串均未比较到串尾
{
if(j==0||S.ch[i]==T.ch[j])
{
++i;
++j; //继续比较后继字符
}
else j=nextval[j]; //模式串向右移动
}
if(j>T.length) return i-T.length; //匹配成功
else return 0; //匹配失败
}
void main()
{
SString a,b;
int n;
printf("请输入主串:\n");
scanf("%s",a.ch);
printf("请输入子串:\n");
scanf("%s",b.ch);
a.length=strlen(a.ch);
b.length=strlen(b.ch);
n=Index_KMP(a,b,1);
if(n==0)
printf("没有找到这样的子串!\n");
else
printf("子串在主串中的位置为:%d\n",n);
}