关于字符串匹配问题——KMP算法

关于字符串匹配问题——KMP算法

(第一次做哪里不好请见谅哈~)
kmp算法: (kmp算法)

由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。

KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。

时间复杂度O(m+n)。

1.next数组:

代码:

int get_next(int next[],string s)
{
    int i=-1,j=0;
    next[j]=i;
    while(j<s.length())
    {
        if(i==-1||s[i]==s[j])
        {
            i++;
            j++;
            next[j]=i;
        }
        else
            i=next[i];
    }
}

以 “abcaba“ 为 想要查找到的字符串 为例

  1. 首先,把第一位的next存成0, next[0]=-1;

  2. 每一位的next都是前面字符串(不包括全部)的最长的前缀与后缀字符串相等的数;

    以“abcaba“ 为例:

    字符串的第二个字母b 前面的字符串为 “a”,所以为0;
    字符串的第三个字母c 前面的字符串为 “ab”,前缀为 a ,后缀为 b,所以为0;
    。。。。。。
    字符串的第六个字母a 前面的字符串为 “abcab”,
    前缀为:“a”,“ab”,“abc”,“abca”;
    后缀为:“b”,“ab”,“cab”,“bcab”,所以最大相等的字符串为“ab”,所以为2。

2.字符串匹配

以“ababcaba”
“abcaba” 为例;

在这里插入图片描述

在这里插入图片描述
3.
在这里插入图片描述
因为a——c 不匹配所以下面的字符串回缩到next[2]的位置(next[2]=0,s[0]=a)。
4.
再次匹配。
在这里插入图片描述

依次匹配后,最终成功,并输出第一次匹配的第一个字母的位置。(若没有匹配到字符串,则输出无字符串匹配)
在这里插入图片描述

3.全部代码:

#include<iostream>
#include<cstring>
using nameapace std;

const int Size = 100;

int get_next(int next[],string s)//获得next数组
{
    int i=-1,j=0;
    next[j]=i;
    while(j<s.length())
    {
        if(i==-1||s[i]==s[j])
        {
            i++;
            j++;
            next[j]=i;
        }
        else
            i=next[i];
    }
}

void KMP(string p,string s,int next[])
{
	int i,j,q=s.length();
	i=0;j=0;
	while(i<p.length()&&j<q)
	{
		if(p[i]==s[j]||j==-1)
		{
            		i++;
           		j++;
		}
		else
           		j=next[j];
	}
	
	if(j==p)
		cout<<"从第"<<i-q+1<<"个字母开始匹配"<<endl;
	else 
		cout<<"无字符串匹配!"<<endl;
}

int main()
{
	int next[Size];
    	string p,s;//p为较长的字符串,s为想要查找到的字符串。
    	cin>>p>>s;

	get_next(next,s);

	KMP(p,s,next);
   	return 0;
}

在这里插入图片描述
若想观察,长的字符串中能查找出多少个想要查找的字符串,可以将KMP代码重把长的字符串都遍历一遍,出现匹配成功,即用 count++即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值