KMP算法

KMP算法是一种字符串模式匹配算法。
什么是字符串的模式匹配?
给定两个串S=“s1s2s3 …sm”和T=“t1t2t3 …tn”,在主串S中寻找子串T的过程叫做模式匹配,T称为模式。
暴力匹配(朴素模式匹配BF)
规定i是主串S的下标,j是模式T的下标。现在假设现在主串S匹配到 i 位置,模式串T匹配到 j 位置。
如果当前字符匹配成功(即S[i] = T[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i] != T[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯到本次失配起始字符的下一个字符,j 回溯到0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int BF(char S[],char T[])
{
    int i=0,j=0;
    while(S[i]!='\0'&&T[j]!='\0')
    {
        if(S[i]==T[j])
        {
            i++;
            j++;
        }
        else
        {
            i=i-j+1;
            j=0;
        }
    }
    if(T[j]=='\0') return (i-j);     //主串中存在该模式返回下标号
    else return -1;     //主串中不存在该模式
}

1. 背景KMP算法一种改进的模式匹配算法,是D.E.Knuth、V.R.Pratt、J.H.Morris于1977年联合发表,KMP算法又称克努特-莫里斯-普拉特操作。它的改进在于:每当从某个起始位置开始一趟比较后,在匹配过程中出现失配,不回溯i,而是利用已经得到的部分匹配结果,将一种假想的位置定位“指针”在模式上向右滑动尽可能远的一段距离到某个位置后,继续按规则进行下一次的比较。

前缀与后缀
前缀:含有首字符不含尾字符的所有子串。
后缀:含有尾字符不含首字符的所有子串。
最长相等前后缀的长度next数组
现在有串P=abaabca,各个子串的最大相等前后缀长度如下表所示:

 

 这样,最长相等前后缀最长长度就会和串P的每个字符产生一种对应关系:

 

 这个表的含义是在当前字符作为最后一个字符时,当前子串所拥有的公共前后缀最长长度。例如当c作为最后一个字符时,当前子串abaabc并没有公共前后缀。

接下来我们就用这个表来引出next数组,next 数组的值是公共前后缀最长长度。我们称next数组中的值为失效函数值。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<iostream>
#include<string>
using namespace std;
void getnext(int *next,string &s)
{
    int i,j;
    next[0]=0;
    j=0;
    for (int i=1;i<s.size();i++)
    {
        while(j>0&&s[j]!=s[i])
        {
            j=next[j-1];
        }
        if (s[j]==s[i]) j++;
        next[i]=j;
    }
}
int Kmp(string s,string t)
{
    int *next;
    next= new int [s.size()+1];
    getnext(next,s);
    int i=0,j=0;
    for (i=0;i<t.size();i++)
    {
        while(j>0&&s[j]!=t[i])
        {
            j=next[j-1];
        }
        if (s[j]==t[i]){
            j++;
        }
        if (j==s.size())
        {
            return i-j+1;
        }
    }
    return -1;
}
int main()
{
    string s,t;
    cin>>t;
    cin>>s;
    cout<<Kmp(s,t)<<endl;
}
/*
in
babaabaabaafg
aabaaf
out
6
 
*/

  

posted @   心悟&&星际  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示