Sunday字符串匹配算法

逛ACM神犇的博客的时候看到的这个神奇的算法

KMP吧,失配函数难理解,代码量长

BF吧,慢,很慢,特别慢。

BM吧,我不会写。。。

现在看到了Sunday算法呀,眼前一亮,神清气爽啊。

字符串匹配算法的效率大概是取决于在发生失配时如何进行下一步的问题。

其他咱就不说了。

这个Sunday算法在发生失配的时候,跳过了尽可能多的字符。

  假设在发生不匹配时S[i]≠T[j],1≤i≤N,1≤j≤M。此时已经匹配的部分为u,并假设字符串u的长度为L。如图1。明显的,S[L+i+1]肯定要参加下一轮的匹配,并且T[M]至少要移动到这个位置(即模式串T至少向右移动一个字符的位置)。

1 Sunday算法不匹配的情况

分如下两种情况:

(1) S[L+i+1]在模式串T中没有出现。这个时候模式串T[0]移动到S[L+i+1]之后的字符的位置。如图2。

2 Sunday算法移动的第1种情况

(2)S[L+i+1]在模式串中出现。这里S[L+i+1]从模式串T的右侧,即按T[M-1]、T[M-2]、…T[0]的次序查找。如果发现S[L+i+1]和T中的某个字符相同,则记下这个位置,记为k,1≤k≤M,且T[k]=S[L+i+1]。此时,应该把模式串T向右移动M-k个字符的位置,即移动到T[k]和S[L+i+1]对齐的位置。如图3。

3 Sunday算法移动的第2种情况

依次类推,如果完全匹配了,则匹配成功;否则,再进行下一轮的移动,直到主串S的最右端结束。该算法最坏情况下的时间复杂度为O(N*M)。对于短模式串的匹配问题,该算法执行速度较快。

Sunday算法思想跟BM算法很相似,在匹配失败时关注的是文本串中参加匹配的最末位字符的下一位字符。如果该字符没有在匹配串中出现则直接跳过,即移动步长= 匹配串长度+1;否则,同BM算法一样其移动步长=匹配串中最右端的该字符到末尾的距离+1。

摘自百度百科

再来看个实例

例如我们要在"substring searching algorithm"查找"search",刚开始时,把子串与文本左边对齐,substring searching algorithmsearch ^结果在第二个字符处发现不匹配,于是要把子串往后移动。但是该移动多少呢?这就是各种算法各显神通的地方了,最简单的做法是移动一个字符位置;KMP是利用已经匹配部分的信息来移动;BM算法是做反向比较,并根据已经匹配的部分来确定移动量。这里要介绍的方法是看紧跟在当前子串之后的那个字符(上图中的‘i‘。显然,不管移动多少,这个字符是肯定要参加下一步的比较的,也就是说,如果下一步匹配到了,这个字符必须在子串内。所以,可以移动子串,使子串中的最右边的这个字符与它对齐。现在子串‘search‘中并不存在‘i‘,则说明可以直接跳过一大片,从‘i‘之后的那个字符开始作下一步的比较,如下图:substring searching algorithm          search          ^比较的结果,第一个字符就不匹配,再看子串后面的那个字符,是‘r‘,它在子串中出现在倒数第三位,于是把子串向前移动三位,使两个‘r‘对齐,如下:substring searching algorithm              search这样就匹配完成了

再比如:

匹配串:O U R S T R O N G X S E A R C H

模式串:S E A R C H

这里我们看到O-S不相同,我们就看匹配串中的O在模式串的位置,没有出现在模式串中。

匹配串:O U R S T R O N G X S E A R C H

模式串: _ _ _ _ _ _ _ _S E A R C H

移动模式串,使模式串的首字符和O的下一个字符对齐。

匹配串:O U R S T R O N G X S E A R C H

模式串:_ _ _ _ _ _ _ _ S E A R C H

继续比较,N-S不相同,字符R出现在模式串,则后移模式串,将把它们对齐

匹配串:O U R S T R O N G X S E A R C H

模式串: _ _ _ _ _ _ _ _ _ _ _ S E A R C H

上个代码吧

var s,check:string;
    next:array [0..26] of longint;

function sunday(s,check:string):longint;
var len_s,len_c,i,pos,j:longint;
begin
    len_s:=length(s);
    len_c:=length(check);
    for i:=1 to 26 do
    next[i]:=len_c+1;
    for i:=1 to len_c do
    next[ord(check[i])-ord(‘a‘)]:=len_c-i;
    pos:=1;
    while pos<(len_s-len_c+1) do
        begin
            i:=pos;
            for j:=1 to len_c do
                begin
                    if s[i]<>check[j] then
                        begin
                            inc(pos,next[ord(s[pos+len_c])-ord(‘a‘)]);
                            break;
                        end;
                    inc(i);
                end;
            if j=len_c then exit(pos);
        end;
    exit(-1);
end;

begin
    readln(s);
    readln(check);
    writeln(sunday(s,check));
end.


 
时间: 2024-10-05 03:47:46

Sunday字符串匹配算法的相关文章

字符串匹配算法之sunday算法

本节介绍一下sunday算法,看一下sunday算法是如何做的呢 首先定义连个字符串 src:abcdacdaahfacabcdabcdeaa pattern:abcde 我们的目的就是在src串中查找pattern串是否存在,找的方法如下 1. 先左对齐,即从src[0].pattern[0]开始,进行依次比较,比较结果如下 arc[0]=pattern[0] 比较成功 arc[1]=pattern[1] 比较成功 arc[2]=pattern[2] 比较成功 arc[3]=pattern[3

典型字符串匹配算法实现 - 单字符串匹配算法

博客源址:http://www.jimye.com/dian-xing-zi-fu-chuang-pi-pei-suan-fa-shi-xian/ 提示:要继续向下看 相信大家对快捷键ctrl+F是做什么用的都应该很熟悉了,无论是文本编辑.网页浏览等程序上它都意味着字符串搜索,我们提供一个关键字,它将找到当前页面上的所有该关键字所在的位置.关键字称为模式串,在文本T中寻找模式串P出现的所有出现的位置,解决这种问题的算法叫做字符串匹配算法.字符串匹配算法可以说是计算机科学中最古老.研究最广泛的问题

KMP字符串匹配算法及next前缀数组的应用

#KMP字符串匹配算法及next前缀数组的应用------ KMP算法通常是我们学习字符串匹配算法时遇见的第一个算法,另外还有Rabin-Karp, Sunday算法等. 相对于其他字符串匹配算法, kmp在字符串中字符重复率低的情况下并不具备优势,那为什么KMP算法会作为经典的教学算法呢? 原因可能是:KMP算法充分利用next前缀数组的信息来优化算法,减小时间复杂度的思路在很多字符串相关问题中能给我们启发. 首先上KMP字符串匹配算法, [leetcode在线测试地址](https://le

字符串匹配算法

字符串匹配问题的形式定义: 文本(Text)是一个长度为 n 的数组 T[1..n]: 模式(Pattern)是一个长度为 m 且 m≤n 的数组 P[1..m]: T 和 P 中的元素都属于有限的字母表 Σ 表: 如果 0≤s≤n-m,并且 T[s+1..s+m] = P[1..m],即对 1≤j≤m,有 T[s+j] = P[j],则说模式 P 在文本 T 中出现且位移为 s,且称 s 是一个有效位移(Valid Shift). 比如上图中,目标是找出所有在文本 T=abcabaabcaba

多模字符串匹配算法之AC自动机—原理与实现

简介: 本文是博主自身对AC自动机的原理的一些理解和看法,主要以举例的方式讲解,同时又配以相应的图片.代码实现部分也予以明确的注释,希望给大家不一样的感受.AC自动机主要用于多模式字符串的匹配,本质上是KMP算法的树形扩展.这篇文章主要介绍AC自动机的工作原理,并在此基础上用Java代码实现一个简易的AC自动机. 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 应用场景-多模字符串匹配 我们现在考虑这样一个问题,在一个文本串t

时空权衡之输入增强 ----字符串匹配算法Horspool算法和Boyer-Moore算法

在算法设计的时空权衡设计技术中,对问题的部分或者全部输入做预处理,对获得的额外信息进行存储,以加速后面问题的求解的思想,我们称作输入增强. 其中字符串匹配算法Horspool算法和Boyer-Moore算法就是输入增强的例子. 首先了解一下字符串匹配的概念.我们把在一个较长的n个字符的串中,寻找一个给定的m个字符的串的问题,称为字符串匹配问题.较长的串称为text,而需要寻找的串称为pattern. 字符串匹配问题的蛮力算法很好理解:我们把pattern与text第一个字符对齐,从左往右比较pa

4种字符串匹配算法:BS朴素 Rabin-karp 有限自动机 KMP(上)

字符串的匹配的算法一直都是比较基础的算法,我们本科数据结构就学过了严蔚敏的KMP算法.KMP算法应该是最高效的一种算法,但是确实稍微有点难理解.所以打算,开这个博客,一步步的介绍4种匹配的算法.也是<算法导论>上提到的.我会把提到的四种算法全部用c/c++语言实现.提供参考学习.下图的表格,介绍了各个算法的处理时间和匹配时间.希望我写的比较清楚.如果不理解的,或者不对的,欢迎留言. 字符串匹配算法及其处理时间和匹配时间 算法 预处理时间 匹配时间 朴素算法 0 O((n-m+1)m) Rabi

字符串匹配算法KMP算法

数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多多余的不符合的匹配做了冗余的比较.假设源字符串长n,字串长m 该算法最差时间复杂度为 m*(n-m+1),记为O(n*m);这里不做过多解释朴素匹配算法. KMP算法: kmp算法不是在源字符串中下手,他是从字串下手,比如我要在源字符串(acabaabaabcacaabc)中匹配一个字符串字串(ab

【算法设计与分析基础】19、字符串匹配算法

package cn.xf.algorithm.ch07inputEnhancement; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; /** * * 功能:字符串匹配算法,(还有一种叫KMP算法的,也是很经典的算法,就是比较复杂) * * 第一步:对于给定的长度为m的模式和在模式文本中用到的字母表,按照上面的描述构造移动表 * 第二步:将模式与文本的开