码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-07-22 23:08:34      阅读:320      评论:0      收藏:0      [点我收藏+]

标签:blog   color   os   数据   io   for   

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

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

需要说明的是:

 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

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

标签:blog   color   os   数据   io   for   

原文地址:http://www.cnblogs.com/bovenson/p/3700398.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!