首页 > 其他分享 >C语言实现字符串的模式匹配

C语言实现字符串的模式匹配

时间:2023-08-14 12:36:00浏览次数:36  
标签:字符 匹配 主串 模式 C语言 算法 字符串 next 模式匹配

一.模式匹配

字符串的模式匹配算法是用来查找一个字符串中是否存在另一个指定的字符串(即模式)的算法。常见的模式匹配算法包括暴力匹配算法、KMP算法、Boyer-Moore算法和Rabin-Karp算法。


暴力匹配算法:暴力匹配算法也称为朴素匹配算法,是最简单的一种字符串匹配算法。它从主串的第一个字符开始与模式串的第一个字符比较,如果相同,则继续比较后面的字符,直到发现不匹配的字符或者模式串完全匹配主串为止。

KMP算法:KMP算法是由Knuth-Morris-Pratt三位作者共同提出的一种高效的字符串匹配算法。其核心思想是利用已经匹配过的信息,尽量减少无用的比较次数。具体实现方式是构建一个next数组,记录模式串中每个前缀子串的最长公共前后缀长度,然后根据next数组跳过一些已经匹配的字符,使得模式串移动的更加快速。

Boyer-Moore算法:Boyer-Moore算法是由Robert S. Boyer和J Strother Moore在1977年提出的一种高效的字符串匹配算法。它通过预处理模式串中每个字符在模式串中出现的位置以及根据坏字符和好后缀规则来决定跳过多少个字符,以达到快速匹配的目的。

Rabin-Karp算法:Rabin-Karp算法是由Richard M. Karp和Michael O. Rabin在1987年提出的一种基于哈希函数的字符串匹配算法。它利用哈希函数对主串和模式串进行哈希计算,并比较哈希值是否相等,从而判断是否匹配。同时,由于哈希函数具有良好的性质,可以在实际应用中获得较高的效率。

在我们考研408范围内需要掌握的也就是第一种暴力匹配算法和KMP匹配算法,今天我们重点来实现这两种算法。


二.暴力匹配算法

1.原理

暴力匹配算法的原理非常简单,它从主串的第一个字符开始,与模式串的第一个字符进行比较,如果相同,则继续比较主串和模式串的下一个字符。如果出现不匹配的情况,则将主串中的指针后移一位,重新从主串的下一个位置开始与模式串进行比较。


具体来说,暴力匹配算法的过程如下:


从主串的第一个字符开始,与模式串的第一个字符进行比较;

如果相同,则继续比较主串和模式串的下一个字符,直到模式串遍历完毕,返回匹配成功;

如果出现不匹配的情况,则将主串中的指针后移一位,重新从主串的下一个位置开始与模式串进行比较,直到主串遍历完毕。如果仍然没有找到匹配的子串,则返回匹配失败。

因为暴力匹配算法是一种最简单的字符串匹配算法,所以它的时间复杂度比较高,平均需要O(mn)次比较操作才能完成匹配,其中m和n分别表示模式串和主串的长度。但是,它也有一些优点,例如实现简单,代码易于理解和调试,适用于小规模的字符串匹配问题等。


2.示意图

C语言实现字符串的模式匹配_字符串

C语言实现字符串的模式匹配_后缀_02




3.C语言算法代码


//暴力匹配算法

int force_search(SString S,SString T){   //第一个字符串为主串,而第二个字符串为模式串

	int i=1,j=1;               //为了好匹配,让字符串从1开始,0的位置存储长度

	while(i<=S.length && j<=T.length){

  if(S.val[i]==T.val[j]){         //匹配到了第一个,继续向下匹配

  	++i;

  	++j;

  }

  else{

  	i=i-j+2;              //指针回退重新匹配,这个代数式来源于笔算验证

  	j=1;

  }

	}

	if(j>T.length)

  return i-T.length;        //匹配成功直至最后一位的下一位,j超出T的长度而i减去T的长度刚好就是匹配起始位置

	else  
  return 0;                  //不成功为了程序继续进行就输出0,我们认为知道匹配不成功就行

}

三.KMP匹配算法

1.原理

KMP算法的核心思想是在匹配过程中尽量利用已经匹配过的信息,从而减少比较次数。具体来说,它通过构建一个next数组,记录模式串中每个前缀子串的最长公共前后缀长度,然后根据next数组跳过一些已经匹配的字符,使得模式串移动的更加快速。


KMP算法的过程如下:


预处理:首先,我们需要构造出模式串p的next数组,用于保存模式串中每个前缀子串的最长公共前后缀长度。具体来说,从模式串的第二个位置开始,依次计算每个位置对应的next值:

(1)如果前缀的第一个字符和后缀的最后一个字符相等,则next值为前一个位置的next值+1; (2)如果前缀的第一个字符和后缀的最后一个字符不相等,或者已经没有前缀可以继续匹配了,则next值为0。


匹配:在匹配过程中,我们将主串s和模式串p的指针都初始化为0,然后依次比较它们的对应字符:

(1)如果当前字符匹配,则分别将指针后移一位,继续比较下一个字符; (2)如果当前字符不匹配,则根据next数组将模式串向右移动若干位,直到匹配或者模式串已经全部移动完成。


在KMP算法中,模式串的移动是根据next数组进行的。具体来说,当模式串中第j个字符与主串中第i个字符不匹配时,我们可以将模式串向右移动max(j-next[j],1)个位置,然后重新开始比较。这样,就能够充分利用已经匹配过的信息,避免重复比较。


总的来说,KMP算法的时间复杂度为O(m+n),其中m和n分别表示模式串和主串的长度。虽然KMP算法需要预处理出next数组,但是它对于稍大规模的字符串匹配问题具有较高的效率和较好的性能表现。

标签:字符,匹配,主串,模式,C语言,算法,字符串,next,模式匹配
From: https://blog.51cto.com/u_16102274/7074841

相关文章

  • 带转义字符的字符串变量 如何不被转义
    问题:val="\061"python中如何使val的输出为r"\061"而不自动转义为"1"val="\061"repr(val)输出的结果是"'1'"这不是我想要的我想要的输出结果是r"\061"解决:val="\061"encoded_val=val.encode().decode('unico......
  • 第16周项目2-用指针玩字符串(1)
    问题及代码:/**Copyright(c)2014,烟台大学计算机学院*Allrightsreserved.*文件名称:MADE69.cpp*作者:孙化龙*完成日期:2014年12月11日*版本号:v1.0**问题描述:字符串连接*输入描述:无*输出描述:链接后的字符串*/#include<iostream>usingnamespacest......
  • 第16周项目2用指针玩字符串(2)
    问题及代码:/**Copyright(c)2014,烟台大学计算机学院*Allrightsreserved.*文件名称:MADE70.cpp*作者:孙化龙*完成日期:2014年12月11日*版本号:v1.0**问题描述:去除字符串str中特定的字符,结果仍保存在字符串str中*输入描述:无*输出描述:去除特定字符后的字......
  • 第13周项目5-字符串操作(1)
    问题及代码:/**Copyright(c)2014,烟台大学计算机学院*Allrightsreserved.*文件名称:MADE59.cpp*作者:孙化龙*完成日期:2014年11月25日*版本号:v1.0**问题描述:统计字母A和每一个数字字符出现的次数*输入描述:字符串*输出描述:字母A和每一个数字字符出现的......
  • Chameleon算法的C语言实现及代码解析
    Chameleon算法的C语言实现及代码解析在计算机科学领域中,算法的设计和实现是非常重要的。而在大量的算法中,Chameleon算法以其独特的特点和应用广泛受到了研究者们的关注。本文将围绕Chameleon算法的C语言实现及其代码解析展开,通过具体的示例来解释其原理和应用。Chameleon算法的C......
  • C语言快速排序降序实现
    C语言快速排序降序实现快速排序是一种常用的排序算法,其灵活性和高效性使其成为程序员们喜爱的排序方式之一。在这篇文章中,我们将探讨如何使用C语言来实现快速排序算法,并实现一个降序排序的例子。C语言快速排序降序实现快速排序算法基于分治的思想,通过选取一个基准元素,将待排序......
  • C语言教程:逐行读取数字的方法
    C语言教程:逐行读取数字的方法在C语言的编程开发中,经常需要处理字符串或文本文件,并从中提取出数字。本文将介绍逐行读取数字的方法,帮助初学者更好地理解和运用。C语言逐行读取数字的方法一、引言数字在计算机编程中扮演着重要的角色,应用广泛。而在处理字符串或文本文件时,需要......
  • C语言中如何获取数组的中位数
    C语言中如何获取数组的中位数在C语言编程中,获取数组的中位数是一项常见而重要的任务。中位数是一个数组中的一个特殊值,它将该数组分为两个等长的部分。当数组长度为奇数时,中位数就是位于数组中间位置的元素;当数组长度为偶数时,中位数是中间两个元素的平均值。7C语言中如何获取数......
  • 利用C语言递归函数解决求5的方法是什么
    利用C语言递归函数解决求5的方法是什么在C语言编程中,递归是一种非常有用的技术,它能够简化问题的解决过程并提高代码的复用性。本文将以求解数字5为例,介绍如何利用C语言递归函数来实现这一任务。9利用C语言递归函数解决求5的方法是什么首先,让我们明确问题的定义。求解数字5的方......
  • C语言求凸包的算法及实现
    C语言求凸包的算法及实现凸包问题是计算几何中的一个重要问题,它描述了一个点集中最小的凸多边形。在本文中,我们将探讨使用C语言来解决凸包问题的算法及其实现。C语言求凸包的算法及实现凸包算法的关键在于如何确定一个点是否在凸包上。对于一个给定的点集,我们可以选择一点作为......