浅析 Sunday 算法
(点击上方公众号,可快速关注)
转自:刘毅
https://www.61mon.com/index.php/archives/213/
背景
Sunday 算法是 Daniel M.Sunday 于 1990 年提出的字符串模式匹配。
其效率在匹配随机的字符串时比其他匹配算法还要更快。Sunday 算法的实现可比 KMP,BM 的实现容易太多。
算法过程
假定主串为 "HERE IS A SIMPLE EXAMPLE",模式串为 "EXAMPLE"。
(1)
从头部开始比较,发现不匹配。则 Sunday 算法要求如下:找到主串中位于模式串后面的第一个字符,即红色箭头所指的 “空格”,再在模式串中从后往前找“空格”,没有找到,则直接把模式串移到“空格” 的后面。
(2)
(3)
找到匹配。
完整代码:
/** * * author : 刘毅(Limer) * date : 2017-07-30 * mode : C++ */ #include <iostream> #include <string> #define MAX_CHAR 256 #define MAX_LENGTH 1000 using namespace std; void GetNext(string & p, int & m, int next[]) { for (int i = 0; i < MAX_CHAR; i++) next[i] = -1; for (int i = 0; i < m; i++) next[p[i]] = i; } void Sunday(string & s, int & n, string & p, int & m) { int next[MAX_CHAR]; GetNext(p, m, next); int j; // s 的下标 int k; // p 的下标 int i = 0; while (i <= n - m) { j = i; k = 0; while (j < n && k < m && s[j] == p[k]) j++, k++; if (k == m) cout << "在" << i << " 处找到匹配\n"; if (i + m < n) i += (m - next[s[i + m]]); else return; } // PS: 匹配失败不作处理 } int main() { string s, p; int n, m; while (cin >> s >> p) { n = s.size(); m = p.size(); Sunday(s, n, p, m); cout << endl; } return 0; }
数据测试如下图: