Sunday算法详解

一:背景

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",

可以看到下图中k指向的字符与m指向的字符相等,

这时就将相等的字符对齐,让j再次指向B字符串的头一个字符,相应地,将i指向主串对应的字符N,

再次比较A[i]和B[j],不等,这时再次寻找主串中在模式串后面的那个字符,

我们看到,模式串的最后一个字符与m指向的主串字符相等,因此再次移动子串,

这时,主串i对应的字符是S,j对应的子串字符也是S,i++, j++,

现在再次不等,m指向字符"D",


三:完整代码
  1. #define _CRT_SECURE_NO_DEPRECATE     
  2. #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1    
  3.   
  4. #include<iostream>   
  5. #include<string>  
  6.   
  7. using namespace std;  
  8.   
  9. int _next[256];  
  10. string dest;  
  11. string pattern;  
  12.   
  13. /* 
  14. 因为i位置处的字符可能在pattern中多处出现(如下图所示),而我们需要的是最右边的位置,这样就需要每次循环判断了,非常麻烦,性能差。这里有个小技巧,就是使用字符作为下标而不是位置数字作为下标。这样只需要遍历一遍即可,这貌似是空间换时间的做法,但如果是纯8位字符也只需要256个空间大小,而且对于大模式,可能本身长度就超过了256,所以这样做是值得的(这也是为什么数据越大,BM/Sunday算法越高效的原因之一)。 
  15. */  
  16. void GetNext()  
  17. {  
  18.     int len = pattern.size();//get the length  
  19.   
  20.     for (int i = 0; i < 256; i++)  
  21.         _next[i] = -1;  
  22.   
  23.     for (int i = 0; i < len; i++)  
  24.         _next[pattern[i]] = i;  
  25. }  
  26.   
  27. int SundaySearch()  
  28. {  
  29.     GetNext();  
  30.   
  31.     int destLen = dest.size();  
  32.     int patternLen = pattern.size();  
  33.   
  34.     if (destLen == 0) return -1;  
  35.   
  36.     for (int i = 0; i <= destLen - patternLen;)  
  37.     {  
  38.         int j = i;//dest[j]  
  39.         int k = 0;//pattern[k]  
  40.   
  41.         for (; k<patternLen&&j < destLen&&dest[j] == pattern[k]; j++, k++)  
  42.             ;//do nothing  
  43.   
  44.         if (k == patternLen)//great! find it!  
  45.             return i;  
  46.         else  
  47.         {  
  48.             if (i + patternLen < destLen)  
  49.                 i += (patternLen - _next[dest[i + patternLen]]);  
  50.             else  
  51.                 return -1;  
  52.         }  
  53.     }  
  54.   
  55.     return -1;  
  56. }  
  57.   
  58. int main()  
  59. {  
  60.     dest = "This is a wonderful city";  
  61.       
  62.     //case one(successful locating)  
  63.     pattern = "wo";  
  64.     int result = SundaySearch();  
  65.     if (result == -1)  
  66.         cout << "sorry,you do not find it!\n";  
  67.     else  
  68.         cout << "you find it at " << result << endl;  
  69.   
  70.     //case two(unsuccessful locating)  
  71.     pattern = "wwe";  
  72.     result = SundaySearch();  
  73.     if (result == -1)  
  74.         cout << "sorry,you do not find it!\n";  
  75.     else  
  76.         cout << "you find it at" << result << endl;  
  77.   
  78.     return 0;  
  79. }  

测试:
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第1章线性代数方程组的解法 1.全主元高斯约当消去法 2.LU分解法 3.追赶法 4.五对角线性方程组解法 5.线性方程组解的迭代改善 6.范德蒙方程组解法 7.托伯利兹方程组解法 8.奇异值分解 9.线性方程组的共轭梯度法 10.对称方程组的乔列斯基分解法 11.矩阵的QR分解 12.松弛迭代法 第2章插值 1.拉格朗日插值 2.有理函数插值 3.三次样条插值 4.有序表的检索法 5.插值多项式 6.二元拉格朗日插值 7.双三次样条插值 第3章数值积分 1.梯形求积法 2.辛普森求积法 3.龙贝格求积法 4.反常积分 5.高斯求积法 6.三重积分 第4章特殊函数 1.г函数、贝塔函数、阶乘及二项式系数 2.不完全г函数、误差函数 3.不完全贝塔函数 4.零阶、一阶和任意整数阶的第一、二类贝赛函数 5.零阶、一阶和任意整数阶的第一、二类变形贝赛函数 6.分数阶第一类贝赛尔函数和变形贝赛尔函数 7.指数积分和定指数积分 8.连带勒让德函数 第5章函数逼近 1.级数求和 2.多项式和有理函数 3.切比雪夫逼近 4.积分和导数的切比雪夫逼近 5.有切比雪夫逼近函数的多项式逼近 第6章特征值问题 1.对称矩阵的雅可比变换 2.变实对称矩阵为三对角对称矩阵 3.三对角矩阵的特征值和特征向量 4.变一般矩阵为赫申伯格矩阵 5.实赫申伯格矩阵的QR算法 第7章数据拟合 1.直线拟合 2.线性最小二乘法 3.非线性最小二乘法 4.绝对值偏差最小的直线拟合 第8章方程求根和非线性方程组的解法 1.图解法 2.逐步扫描法和二分法 3.割线法和试位法 4.布伦特方法 5.牛顿拉斐森法 6.求复系数多项式根的拉盖尔方法 7.求实系数多项式根的贝尔斯托方法 8.非线性方程组的牛顿拉斐斯方法 第9章函数的极值和最优化 1.黄金分割搜索法 2.不用导数的布伦特法 3.用导数的布伦特法 4.多元函数的下山单纯形法 5.多元函数的包维尔法 6.多元函数的共轭梯度法 7.多元函数的变尺度法 8.线性规划的单纯形法 第10章傅里叶变换谱方法 1.复数据快速傅里叶变换算法 2.实数据快速傅里叶变换算法一 3.实数据快速傅里叶变换算法二 4.快速正弦变换和余弦变换 5.卷积和逆卷积的快速算法 6.离散相关和自相关的快速算法 7.多维快速傅里叶变换算法 第11章数据的统计描述 1.分布的矩——均值、平均差、标准差、方差、斜差和峰态 2.中位数的搜索 3.均值与方差的显著性检验 4.分布拟合的X平方检验 5.分布拟合的K-S检验法 第12章解常微分方程组 1.定步长四阶龙格库塔法 2.自适应变步长的龙格库塔法 3.改进的中点法 4.外推法 第13章偏微分方程的解法 1.解边值问题的松驰法 2.交替方向隐式方法 这些算法将为千千万万非计算机专业的工程技术人员架起一座方便快捷的桥梁, 并能缩短应用软件的编制周期,减少重复劳动,达到事业功倍的效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值