模式字符串匹配问题(KMP算法)

这两天又看了一遍《算法导论》上面的字符串匹配那一节,下面是实现的几个程序,可能有错误,仅供参考和交流。

关于详细的讲解,网上有很多,大多数算法及数据结构书中都应该有涉及,由于时间限制,在这就不重复了。

需要说明的是:

 stra:主串,及需要从中寻找模式串的字符串

 strb:模式串

 《算法导论》上面包括严蔚敏老师《数据结构》,字符串下表是按从1开始,并且《数据结构》一书中貌似吧字符串的第一个字符用来储存字符串长度。这里我改成了0。

 maxlen :字符串的最长长度

1. 朴素算法 (最容易理解的,时间复杂度有点高 预处理时间:O(0),查询时间:O((n-m-1) * m))

?





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

/**

字符串模式匹配的朴素算法

s为偏移量

*/

#include <cstdio>

#include <iostream>

#include <cstring>

using
namespace std;

const
int maxlen = 1000;

void
NAIVE_STRING_MATCHER(char* stra, char* strb)

{

    int
n(strlen(stra)), m(strlen(strb));

    for
(int s(0);s <= n - m; ++s)

        if
(stra[s] == strb[0])

        {

            bool
flag = true;

            for
(int i(0); i < m; ++i)

                if
(stra[s+i] != strb[i])

                {

                    flag = false;

                    break;

                }

            if
(flag)

            {

                cout<<"Pattern occurs with shifts "<<s<<endl;

                return;

            }

        }

    cout<<"Pattern doesn‘t occur."<<endl;

}

int
main()

{

    char
stra[maxlen], strb[maxlen];

    while(cin>>stra && cin>>strb)

        NAIVE_STRING_MATCHER(stra, strb);

    return
0;

}

  

  2. Rabin & Karp 算法 (这个算法让我想起了哈希表 预处理时间:O(m),查询时间:O((n-m-1) * m), 哈哈,
不比朴素算法快,因为看了,写了,就贴出来了,可以不看)

?





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

/**

Rabin, Karp 发现的字符串匹配算法

*/

#include <cstdio>

#include <iostream>

#include <cstring>

using
namespace std;

const
int maxlen = 10000;

int d(10), mod(100000007);

void
RABIN_KARP_MATCHER(char* stra, char* strb)

{

    int
n(strlen(stra)), m(strlen(strb)), p(0), t(0), h(1);

    //preprocessing

    for
(int i(0); i < m-1; ++i)

        h = i ? h * d % mod : d % mod;

    for
(int i(0); i < m; ++i)

    {

        p = (d * p + strb[i]) % mod;

        t = (d * t + stra[i]) % mod;

    }

    for
(int s(0); s <= n - m; ++s)

    {

        if
(p == t)

        {

            bool
flag = true;

            for
(int j(0); j < m; ++j)

                if
(stra[s+j] != strb[j])

                {

                    flag = false;

                    break;

                }

            if
(flag)

            {

                cout<<"Pattern occurs with shifts "<<s<<endl;

                return
;

            }

        }

        t = (d * (t - (stra[s]) * h) + stra[s+m]) % mod;

    }

    cout<<"Pattern doesn‘t occur."<<endl;

}

int
main()

{

    char
stra[maxlen], strb[maxlen];

    while(cin>>stra && cin>>strb)

        RABIN_KARP_MATCHER(stra, strb);

    return
0;

}

  3.《算法导论》还给了有限自动机的算法,处理时间要比KMP算法长,查询时间复杂度一样,可以说,KMP是对有限自动机预处理优化之后的算法。下面是

KMP算法   预处理时间:O(m),查询时间:O(n)

  事先说明:算法是《算法导论》思路,但是却用了严蔚敏老师《数据结构》中的一些变量,比如next数组,本以为其和《算法导论》中的 pi
(圆周率的符号,在这用了拼音) 数组一样,现在看来有一点不一样。

?





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

#include <cstdio>

#include <iostream>

#include <algorithm>

#include <cstring>

using
namespace std;

const
int maxlen = 10000;

void
get_next(char* strb, int* next)

{

    int
i(1), j(-1), d(strlen(strb));

    next[0] = -1;

    for
(; i < d; ++i)

    {

        while(j >= 0 && strb[j+1] != strb[i])

            j = next[j];

        if
(strb[j+1] == strb[i])

            j += 1;

        next[i] = j;

    }

}

void
KMP_MATCHER(char* stra, char* strb)

{

    int
n(strlen(stra)), m(strlen(strb)), next[maxlen];

    get_next(strb, next);

    int
i(0), j(-1);

    for
(int i(0); i < n; ++i)

    {

        while(j >= 0 && strb[j+1] != stra[i])

            j = next[j];

        if
(strb[j+1] == stra[i])

            j += 1;

        if
(j == m - 1)

        {

            cout<<"Pattern occurs with shifts "<<i - j<<endl;

            return
;

        }

    }

    cout<<"Pattern doesn‘t occurs."<<endl;

}

int
main()

{

    char
stra[maxlen], strb[maxlen];

    while(cin>>stra && cin>>strb)

        KMP_MATCHER(stra, strb);

    return
0;

}

  再次重申:代码可能有错,欢迎大家指正。

模式字符串匹配问题(KMP算法),码迷,mamicode.com

时间: 2024-10-26 17:39:19

模式字符串匹配问题(KMP算法)的相关文章

[算法系列之二十六]字符串匹配之KMP算法

一 简介 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 二 基于部分匹配表的KMP算法 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含搜索串"ABCDABD"? 步骤1:字符串"BBC ABC

字符串匹配(KMP 算法 含代码)

主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知识 串(string或字符串)是由零个或多个字符组成的有限序列,一般记为 当中s是串的名,用单引號括起来的字符序列是串的值:ai(1<=i<=n)能够是字母.数值或其它字符.串中字符的数组 n称为串的长度.零个字符的串称为空串,它的长度为0 串中随意个连续的字符组成的子序列称为该串的子串. 包括子

字符串匹配的KMP算法

html, body { font-size: 15px; } body { font-family: Helvetica, "Hiragino Sans GB", 微软雅黑, "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.6; color: ; background-color: ; margin: 0; padding: 16px 20px; } h1, h2, h

字符串匹配与KMP算法笔记

>>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个一个进行比较, 如果不成功则模式串向右移动一个单位,直到匹配成功或者到达匹配串最后仍然不成功,返回失败. 很明显,这种算法有很多的地方可以优化,假设要搜索的串为S,长度为n,要匹配的串为M,长度为m,时间复杂度为O(nm). >>KMP算法 Knuth-Morris-Pratt算法以三个发明者命名

字符串匹配之KMP算法

1.前言: leetcode上的28. Implement strStr()就是一个字符串匹配问题.字符串匹配是计算机的基本任务之一.所以接下来的两篇日志,都对相关的算法进行总结. 2.暴力求解算法 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0.相当于每次匹配失败时,i 回溯

算法——字符串匹配之KMP算法

前言 本节介绍Knuth-Morris-Pratt字符串匹配算法(简称KMP算法).该算法最主要是构造出模式串pat的前缀和后缀的最大相同字符串长度数组next,和前面介绍的<朴素字符串匹配算法>不同,朴素算法是当遇到不匹配字符时,向后移动一位继续匹配,而KMP算法是当遇到不匹配字符时,不是简单的向后移一位字符,而是根据前面已匹配的字符数和模式串前缀和后缀的最大相同字符串长度数组next的元素来确定向后移动的位数,所以KMP算法的时间复杂度比朴素算法的要少,并且是线性时间复杂度,即预处理时间复

字符串匹配的KMP算法(转)

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth. 这种算法不太容易理解,网上有很多解释,但读起来都很费劲.直到读到Jake Boxer的文章,我才真正理解这种算法.下面,我用自己的语言

字符串匹配的KMP算法(转载)

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth. 这种算法不太容易理解,网上有很多解释,但读起来都很费劲.直到读到Jake Boxer的文章,我才真正理解这种算法.下面,我用自己的语言

[转] 字符串匹配的KMP算法

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth. 这种算法不太容易理解,网上有很多解释,但读起来都很费劲.直到读到Jake Boxer的文章,我才真正理解这种算法.下面,我用自己的语言

字符串匹配暴力算法 与 字符串匹配的KMP算法

声明:先看一下阮一峰的网络日志关于字符串的KMP算法的讲解.本文图片均引用于这篇日志. 在先前的笔试中遇到了关于字符串匹配的问题,一时脑袋卡壳没写好算法.现在就来分析分析 暴力算法和KMP算法各自原理,以及代码实现,之间差异,并且总结一下好算法的一般思路. =========================================================================== 各自原理: 暴力算法: 1. 我们把长的字符串做为一个文本字符串,命名为strText,把