一.Sunday算法简介
Sunday算法在我看来比起Kmp和bm都更加容易理解,代码实现也更加简洁。Sunday算法由Daniel M.Sunday在1990年提出,它的思想跟BM算法很相似只不过Sunday算法是从前往后匹配,在匹配失败时关注的是主串中参加匹配的最末位字符的下一位字符。
二.核心思想
Sunday算法与bm算法不同,它是从前往后匹配字符。当出现坏字符时我们所关注的字符是主串中与模式串最后一位对齐的下一位字符,如下图所示
(1)第一种情况
关注字符与模式串的首字符不相同,直接将整个模式串向后挪动,让模式串的第一位和关注字符的下一位对齐,如下图所示
(2)第二种情况
关注字符与模式串的首字符相同 ,将模式串向后移动,使关注字符与模式串的首字符对齐,如下图所示
三.代码模板
#include <iostream>
#include <string>
using namespace std;
const int maxNum = ;
int shift[maxNum];
int Sunday(const string& T, const string& P) {
int n = T.length();//主串
int m = P.length();//匹配串 // 默认值,移动m+1位
for(int i = ; i < maxNum; i++) shift[i] = m + ;
// 模式串P中每个字母出现的最后的下标
// 所对应的主串参与匹配的最末位字符的下一位字符移动到该位,所需要的移动位数
for(int i = ; i < m; i++) shift[P[i]] = m - i;
// 模式串开始位置在主串的哪里
int j,s = ;
// 模式串已经匹配到主串的位置
while(s <= n - m)
{
j = ;
while(T[s + j] == P[j])
{
j++;
// 匹配成功
if(j >= m) return s;
}
// 找到主串中当前跟模式串匹配的最末字符的下一个字符
// 在模式串中出现最后的位置
// 所需要从(模式串末尾+1)移动到该位置的步数
s += shift[T[s + m]];
}
return -;
}
int main() {
// 主串和模式串
string T, P;
while(true) {
// 获取一行
getline(cin, T);
getline(cin, P);
int res = Sunday(T, P);
if(res == -) {
cout << "主串和模式串不匹配。" << endl;
} else {
cout << "模式串在主串的位置为:" << res << endl;
}
}
return ;
}