• 字符串匹配值Sunday算法


    实现strStr()

    题目:实现 strStr()
    实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

    力扣练习题

    示例1:

    输入: haystack = "hello", needle = "ll"
    输出: 2
    
    • 1
    • 2

    示例2:

    输入: haystack = "aaaaa", needle = "bba"
    输出: -1
    
    • 1
    • 2

    说明:

    当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

    对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
    02、Sunday 匹配

    Sunday 算法是 Daniel M.Sunday 于1990年提出的字符串模式匹配。其核心思想是:在匹配过程中,模式串发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。

    因为该问是字符串匹配篇第一讲,所以先普及几个概念:

    • 串:串是字符串的简称 空串:长度为零的串称为空串
    • 主串:包含子串的串相应地称为主串
    • 子串: 串中任意个连续字符组成的子序列称为该串的子串
    • 模式串:子串的定位运算又称为串的模式匹配,是一种求子串第一个字符在主串中序号的运算。被匹配的主串称为目标串,子串称为模式串。

    了解这些基本概念,回到这个算法。Sunday匹配不是说这人在周末发现了这个算法,而是这人名字叫星期天(可能父母总加班,所以起了这么个名)。听起来牛叉的不得了,其实是个啥意思:

    假若我们的目标串为:Here is a little Hao
    模式串为:little

    一般来讲,字符串匹配算法第一步,都是把目标串和模式串对齐。不管是KMP,BM,SUNDAY都是这样。
    在这里插入图片描述
    而对于SUNDAY算法,我们从头部开始比较,一旦发现不匹配,直接找到主串中位于模式串后面的第一个字符,即下面绿色的 “s”。(这里说明一下,为什么是找模式串后面的第一个字符。在把模式串和目标串对齐后,如果发现不匹配,那肯定需要移动模式串。问题是需要移动多少步。各字符串匹配算法之间的差别也来自于这个地方,对于KMP,是建立部分匹配表来计算。BM,是反向比较计算移动量。对于SUNDAY,就是找到模式串后的第一个字符。因为,无论模式串移动多少步,模式串后的第一个字符都要参与下一次比较,也就是这里的 “s”)
    在这里插入图片描述
    找到了模式串后的第一个字符 “s”,接下来该怎么做?我们需要查看模式串中是否包含这个元素,如果不包含那就可以跳过一大片,从该字符的下一个字符开始比较
    在这里插入图片描述因为仍然不匹配(空格和l),我们继续重复上面的过程。找到模式串的下一个元素:t
    在这里插入图片描述
    现在有意思了,我们发现 t 被包含于模式串中,并且 t 出现在模式串倒数第3个。所以我们把模式串向前移动3个单位:
    在这里插入图片描述
    有内味了,我们发现竟然匹配成功了,是不是很神奇?证明的过程今天暂且不谈(后面我会出一个算法证明篇,来证明之前讲过的一些算法。我需要你做的是,掌握上面这些!

    捞干货,这个过程里我们做了一些什么:

    • 对齐目标串和模式串,从前向后匹配
    • 关注主串中位于模式串后面的第一个元素(核心)
    • 如果关注的字符没有在子串中出现则直接跳过
    • 否则开始移动模式串,移动位数 = 子串长度 - 该字符最右出现的位置(以0开始)

    03、算法应用
    下面给出该算法的C++实现

    class Solution {
    public:
    	int strStr(string haystack, string needle)
    		/* implementation of Sunday (Daniel M.Sunday. 1990) algorithm */
    	{
    		bulidMap(needle);
    		int i = 0;
    		int n = needle.size();
    		while (i < haystack.size()) {
    			int rv = match(haystack, i, needle);
    			/* found a ans */
    			if (rv != -1) {
    				return rv;
    			}
    			/* not match otherwise */
    			if (i + n >= haystack.size()) break;
    			char ch_next = haystack[i + n];
    			/* calculate move steps */
    			int move = 1;
    
    			int lastOccurIndx = indexOf(ch_next);
    			if (lastOccurIndx == -1) move = needle.size() + 1;  /* case1: next char not occured int pattern str */
    			else move = needle.size() - lastOccurIndx;          /* case2: otherwise */
    			i += move;
    		}
    		return -1;
    	}
    private:
    	// unordered_map<int, int> _map;
        int _map[26];
    	inline void bulidMap(const string patStr) {
            for(int i = 0; i < 26; i++) _map[i] = -1;
    
    		for (int i = 0; i < patStr.size(); i++) {
    			_map[patStr[i]-'a'] = i;
    		}
    	}
    
    	inline int indexOf(char target) 
        /* index of char target in pattern str */ 
        {
            return _map[target-'a'];
    	}
    
    	inline int match(const string str, int start, const string pat) 
    	/* tell weather pat is a substr of str begining at position `start`*/
    	{
    		int i, j = 0;
    		for (int i = start; i < str.size(); i++) {
    			if (str[i] != pat[j++]) return -1;
    			if (j == pat.size()) break;
    		}
    		if (j != pat.size()) return -1;
    		// they matched at pos: start
    		return start;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
  • 相关阅读:
    【无标题】
    集成经验模态(EEMD)原理详解与python实现
    Elasticsearch 浅尝
    JSON数据格式
    代码随想录 单调栈part3
    初学者看 “图“
    医学影像相关开源数据集资源汇总
    Java的HTTPClient工具类(附代码实现)
    未来战争机器人
    系统性能调优:提升服务器响应速度
  • 原文地址:https://blog.csdn.net/qq_41314786/article/details/125490344