一:背景
Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配。其效率在匹配随机的字符串时比其他匹配算法还要更快。Sunday算法的实现可比KMP,BM的实现容易太多。
二:分析
假设我们有如下字符串:
A = "LESSONS TEARNED IN SOFTWARE TE";
B = "SOFTWARE";
Sunday算法的大致原理是:
先从左到右逐个字符比较,以我们的字符串为例:
开始的时候,我们让i = 0, 指向A的第一个字符; j = 0 指向B的第一个字符,分别为"L"和"S",不等;这个时候,Sunday算法要求,找到位于A字串中位于B字符串后面的第一个字符,即下图中 m所指向的字符"T",在模式字符串B中从后向前查找是否存在"T",
![](https://img-blog.csdn.net/20160714221937697)
可以看到下图中k指向的字符与m指向的字符相等,
![](https://img-blog.csdn.net/20160714222222080)
这时就将相等的字符对齐,让j再次指向B字符串的头一个字符,相应地,将i指向主串对应的字符N,
![](https://img-blog.csdn.net/20160714222349968)
再次比较A[i]和B[j],不等,这时再次寻找主串中在模式串后面的那个字符,
![](https://img-blog.csdn.net/20160714222451518)
我们看到,模式串的最后一个字符与m指向的主串字符相等,因此再次移动子串,
![](https://img-blog.csdn.net/20160714222940914)
这时,主串i对应的字符是S,j对应的子串字符也是S,i++, j++,
![](https://img-blog.csdn.net/20160714223051525)
现在再次不等,m指向字符"D",
![](https://img-blog.csdn.net/20160714223156855)
三:完整代码
- #define _CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
-
- #include<iostream>
- #include<string>
-
- using namespace std;
-
- int _next[256];
- string dest;
- string pattern;
-
-
-
-
- void GetNext()
- {
- int len = pattern.size();
-
- for (int i = 0; i < 256; i++)
- _next[i] = -1;
-
- for (int i = 0; i < len; i++)
- _next[pattern[i]] = i;
- }
-
- int SundaySearch()
- {
- GetNext();
-
- int destLen = dest.size();
- int patternLen = pattern.size();
-
- if (destLen == 0) return -1;
-
- for (int i = 0; i <= destLen - patternLen;)
- {
- int j = i;
- int k = 0;
-
- for (; k<patternLen&&j < destLen&&dest[j] == pattern[k]; j++, k++)
- ;
-
- if (k == patternLen)
- return i;
- else
- {
- if (i + patternLen < destLen)
- i += (patternLen - _next[dest[i + patternLen]]);
- else
- return -1;
- }
- }
-
- return -1;
- }
-
- int main()
- {
- dest = "This is a wonderful city";
-
-
- pattern = "wo";
- int result = SundaySearch();
- if (result == -1)
- cout << "sorry,you do not find it!\n";
- else
- cout << "you find it at " << result << endl;
-
-
- pattern = "wwe";
- result = SundaySearch();
- if (result == -1)
- cout << "sorry,you do not find it!\n";
- else
- cout << "you find it at" << result << endl;
-
- return 0;
- }
测试:
![](https://img-blog.csdn.net/20160229193528807)