xtu-数据结构实验4-字符串匹配查找(KMP算法)

一、题目描述
  字符匹配查找(给定一个模式串,在主串中查找与模式串匹配的所有结果,输出匹配的位置)——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);
}

五、运行结果在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值