符串匹配 — Sunday

此算法比BM算法的效率还要高。Sunday算法没有规定必须从模式头部开始比较还是从模式尾部开始比较。所以两种方法都是可以的。

下面是个例子,假设从头开始比较。
文本:A B C A B D B C D
模式:B C D

A≠B,那么查看文本中越出比较范围后的第一个字符(这里为A)是否在模式中,如果在,则两者对齐,否则跳过A。这里直接跳过A。
文本:A B C A B D B C D
模式:        B C D

D≠C,而比较范围后的第一个字符C在模式中,所以将它们对齐。
文本:A B C A B D B C D
模式:            B C D

可以看到,模式总共只进行了两次移动,而BM算法和Horspool算法移动次数都不止两次。由此可见,此算法的效率是非常高的, 而且Sunday算法的思想极其简单

代码如下:
#include <iostream>
#include <string>
#include <map>
#include <vector>
 
using namespace std;
 
// 计算坏符号移动表
void Get_Next(const string &text, const string &pattern, map<char, int> &next)
{
    int text_len = text.size();
    int pattern_len = pattern.size();
 
    for (int i = 0; i < text_len; i++)
        next.insert(make_pair(text[i], pattern_len + 1));
 
    for (int i = 0; i < pattern_len; i++)
        next[pattern[i]] = pattern_len - i;
}
 
void Sunday(const string &text, const string &pattern, vector<int> &result)
{
    int text_len = text.size();
    int pattern_len = pattern.size();
    map<char, int> next;    // 保存坏字符的表
 
    Get_Next(text, pattern, next);
 
    for (int i = 0; i < text_len - pattern_len + 1; /* NULL */)
    {
        int after_last = i + pattern_len;
        int text_pos = i;
        int pattern_pos;
 
        for (pattern_pos = 0; pattern_pos < pattern_len; /* NULL */)
        {
            if (text[text_pos] == pattern[pattern_pos])
            {
                text_pos++;
                pattern_pos++;
            }
            else
            {
                i += next[text[after_last]];
                break;
            }
        }
        if (pattern_pos == pattern_len)
        {
            result.push_back(i);
            i++;
        }
             
    }
}
 
int main()
{
    string text = "hello world good google Nestle people google hello this is a test google";
    string pattern = "google";
    vector<int> result;
 
    Sunday(text, pattern, result);
 
    int cnt = 1;
    for (vector<int>::iterator iter = result.begin(); iter != result.end(); ++iter)
        cout << "match " << cnt++ << " = " << *iter << endl;
 
    system("pause");
    return 0;
}


运行结果:

你可能感兴趣的:(符串匹配 — Sunday)