字符串匹配算法1:暴力匹配算法

字符串匹配算法1:暴力匹配算法
https://blog.csdn.net/lqy971966/article/details/99770472

字符串匹配算法2:KMP算法
https://blog.csdn.net/lqy971966/article/details/105712559

字符串匹配算法3:Boyer-Moore 算法
https://blog.csdn.net/lqy971966/article/details/106026651

1. 问题

有一个主串S,和一个模式串P,现在要查找P是否是主串S中的的子串。
主串 S串: abcd
模式串P串: bcd

2. 解决思想

2.1 举例

第一次匹配,a!=b,模式串往后移动一位。
在这里插入图片描述
第二次匹配,b=b,匹配后一位
在这里插入图片描述
第三次匹配,c=c,匹配后一位
在这里插入图片描述
第四次匹配,d=d,匹配完成。
在这里插入图片描述
如上图所示,暴力匹配的思路:依次用模式串匹配主串串的每一位,若模式串第一位匹配失败,则匹配主串的第二位,依次类推。

2.2 匹配思想

思想:
1. 依次从主串的首字符开始,与模式串逐一进行匹配;
2. 遇到失配时,则移到主串的第二个字符,将其与模式串首字符比较,逐一进行匹配;
3. 重复上述步骤,直至能匹配上,或剩下主串的长度不足以进行匹配。

3. 代码

假设现在主串S匹配到 i 位置,模式串P匹配到 j 位置,则有:

  1. 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;

  2. 如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0。

     //入参:pcSrc为主串abcd, pcDst为模式串 bcd
     int BF_Match(char *pcSrc, char *pcDst) {
     
     	int iSrcLoop, iDstLoop, iTmp;
     	int iSrclen  = strlen(pcSrc);
     	int iDstlen = strlen(pcDst);
     	
     	/*
     	for循环遍历主串,从头开始匹配模式串;
     	匹配失败,主串往后移动一位,继续匹配,依次。
     	注意: 这里主串每往后移动时,
     	需要计算主串剩余长度需要大于模式串长度,否则匹配无意义
     	*/
     	for(iSrcLoop = 0, iDstLoop = 0; iSrcLoop <= iSrclen  - iDstlen;
     	iSrcLoop++, iDstLoop = 0) {
     		iTmp = iSrcLoop;
     		
     		/*
     		while循环遍历模式串,模式串匹配中主串,
     		则模式串和主串都后移一位继续匹配,否则跳出
     		*/
     		while( (pcSrc[iTmp] == pcDst[iDstLoop]) & (iDstLoop < iDstlen) ) {
         			iTmp++;
        			iDstLoop++;
     		}
     		
     		// matched OK
     		if(iDstLoop == iDstlen ) {
         		return iSrcLoop;
     		}
      	}
     	// [pcDst] is not a substring of [pcSrc]
     	return -1;
     }
    

4. 时间复杂度:

iSrcLoop 在主串移动次数(外层的for循环)有 n−p(iSrclen- iDstlen ) 次,在失配时 iDstLoop 移动次数最多有(p-1)iDstLoop−1次(最坏情况下);
因此,复杂度为 O(n*p)

5. 暴力匹配缺点:

5.1 重复匹配

上一次匹配失败后,下一次匹配的位置

  1. 主串的起始位置 = 上一轮匹配的起始位置 T + 1;
  2. 模式串的起始位置 = 首字符P[0]。
    如此未能利用已经匹配上的字符的信息,造成了重复匹配

5.2 例子

主串T=“ababcabcacbab”,
模式串P=“abcac”

比如:第一次匹配失败时,主串、模式串失配位置的字符分别为 a 与 c,
下一次匹配时主串、模式串的起始位置分别为T[1]与P[0];
而在模式串中c之前是ab,未有重复字符结构,因此T[1]与P[0]肯定不能匹配上,这样造成了重复匹配。
直观上,下一次的匹配应从T[2]与P[0]开始。

参考:

https://blog.csdn.net/v_july_v/article/details/7041827
https://www.cnblogs.com/en-heng/p/5091365.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值