一、题目描述
字符匹配查找(给定一个模式串,在主串中查找与模式串匹配的所有结果,输出匹配的位置)——KMP算法
二、需求分析
1.此程序为交互式,用户需要根据提示输入主串与模式串。
2.主串与模式串均可由大、小写字母、空格等字符组成的字符串,以回车表示结束输入。
3.用户输入主串与模式串后,并会输出结果,若可匹配,则输出所有可匹配的位置,否则输出提示“主串中没有与模式串匹配的子串”。
三、程序设计
解决字符串匹配的算法的方法很多,在这里我选择效率较高的KMP算法,关于KMP算法的实现如下:
我是黑体字
(1)失配函数的实现:在实现KMP算法前我们得先得到模式串的失配函数值(即:失配时模式串应从哪个位置开始比较),用next数组存储(next[j]表示模式串第j个位置失配时模式串从该位置开始进行比较)。这里,我们可把求next函数值的问题看成是一个模式匹配的问题,整个模式串既是主串又是模式串,从而当前在匹配的过程中,我们可以计算出每位地失配函数值。
(2)KMP函数的实现: 有了next失配函数值,我们便可以设计KMP函数了,KMP算法大概就是从主串首位开始对模式串进行比较,然后模式串后移,中途若匹配成功便记录当前位置。在匹配过程产生失配时,指针i不变,指针j退回到next[j]的位置上重新比较,并且当指针j退回0时,指针i与j需同时增1。即主串的第i个字符和模式的第1个字符不等,应从主串第i+1个字符起重新进行匹配。(指针i指的是主串的位置,j指的是模式串的位置)
四、代码(附一些注释)
#include<stdio.h>
#include<string.h>
#define S_size 10000
#define T_size 10000
#define next_size 10000
void get_next(char T[],int next[]);//失配函数值的获取
int Index_KMP(char S[],char T[],int next[],int pos);//KMP算法的实现
int main()
{
char S[S_size];// 主串
char T[T_size];//模式串
int next[next_size];// 失配函数值
printf("请输入主串:");
gets(S);
printf("请输入模式串:");
gets(T);
get_next(T,next);//得到模式串T的失配函数值
int n=0,k=0;//k标志是否存在有匹配的子串
while(n!=-1)
{
n=Index_KMP(S,T,next,n);
if(n!=-2)
{
printf("主串中第 %d 个字符处可与子串匹配\n",n);
k=1;
}
n=n+1;
}
if(k==0) printf("主串中没有与模式串匹配的子串\n");
return 0;
}
void get_next(char T[],int next[])
{
int i=0,j=-1;
next[0]=-1;
int T_length=strlen(T);
while(i<T_length)
{
if(j==-1||T[i]==T[j])
{
++i;
++j;
if(T[i]!=T[j]) next[i]=j;
else next[i]=next[j];
}
else j=next[j];
}
}
int Index_KMP(char S[],char T[],int next[],int pos)//第pos个字符处开始比较
{
int i=pos,j=0;
int S_length=strlen(S);
int T_length=strlen(T);
while(i<S_length&&j<T_length)
{
if(j==(-1)||S[i]==T[j])//继续比较后继字符
{
i++;
j++;
}
else j=next[j];//模式串向右移动
}
if(j>=T_length) return (i-T_length+1);//匹配成功
else return (-2);
}
五、运行结果