代码随想录 字符串之kmp算法

一、28. 找出字符串中第一个匹配项的下标(串匹配问题)

https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/

class Solution {
public:
    //获得模式串的next表 表中的元素值代表与其重复的前缀中最后一个元素的下标(虚拟通配字符 下标-1)
    void getnext(int *next,const string &s){
        //定义两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置
        int i = 0;
        int j = -1;
        //j所指为通配字符 next表第一个元素值为-1
        next[0] = -1;
        for(i = 1;i<s.size();i++){//i从1开始,j+1从0开始 刚好错开1位
            while(j>=0 && s[i]!=s[j+1]){// 前后缀不相同,j=-1或前后缀相同时跳出循环
                j = next[j];// 向前回退
            }
            if(s[i] == s[j+1]){// 找到相同的前后缀
                j++;
            }
            next[i] = j; // 将j(前缀的长度)赋给next[i]
        }
        

    }
    int strStr(string haystack, string needle) {
        if(needle.size() == 0){
            return 0;
        }
        int next[needle.size()];
        //生成next表 next表元素值是所指元素的后缀与前缀重复时,前缀末元素的下标
        getnext(next,needle);

        int j = -1;
        for(int i = 0;i<haystack.size();i++){
            //若模式串与文本串所指字符不匹配,进入循环查找匹配项(j!=-1)或通配项(j=-1)
            while(j>=0 && haystack[i] != needle[j+1]){
                j = next[j];
            }

            //若匹配,则模式串指针向后移动 比较下一个字符
            if(haystack[i]== needle[j+1]){
                j++;
            }
            
            //模式串指针指向最后一个元素时,返回文本串匹配位置的第一个元素索引
            if(j == (needle.size()-1)){
                return (i-needle.size()+1);
            }
        }
        return -1;
    }
};

二、459. 重复的子字符串

https://leetcode.cn/problems/repeated-substring-pattern/

class Solution {
public:
     //生成next表
    void getnext(int* next,string &s){
        int j = -1;
        next[0] = -1;

        for(int i = 1;i<s.size();i++){
            while(j >= 0 && s[i] != s[j+1]){
                j = next[j];
            }
            if(s[i] == s[j+1]){
                j++;
            }
            next[i] = j;
        }
    }
    
    bool repeatedSubstringPattern(string s) {
        //自身子串可以与自身完全匹配多次
        //最长前后缀,剩余的元素即为重复元素
        
        //字符串长度要>=2,才会重复
        if(s.size() <= 1){
            return false;
        }
        
        //next表
        int next[s.size()];
        getnext(next,s);

        //如果是重复串,最长前后缀一定出现在末元素
        //如果是重复串,前面部分即为重复部分
        //如果是非重复串,前后缀的中间部分是非重复部分

        //len 为总长度-一个重复子串
        int len = s.size()-next[s.size()-1]-1;

        //若s是重复子串,len为剩余部分的长度
        //若s为非重复子串,len为重复部分+非重复部分的长度
        //(2*重复部分+非重复部分) % (重复部分+非重复部分) 是否等于0
        //非重复部分=0,则上式=0;非重复部分!=0,上式!=0
        if(next[s.size()-1] != -1 && s.size() % len == 0){//next[s.size()-1] != -1 等于-1,代表没有重复前后缀,自然也就不是重复子串
            return true;
        }
        return false;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种用于字符串匹配的算法,它的核心思想是利用部分匹配表来避免不必要的比较。下面是KMP算法的原理和实现步骤: 1. 部分匹配表的计算: - 部分匹配值是指字符串的前缀和后缀的最长公共部分的长度。 - 部分匹配表是一个数组,记录了每个位置的部分匹配值。 - 部分匹配表的计算可以通过动态规划的方式进行,具体步骤如下: - 初始化部分匹配表的第一个元素为0。 - 从第二个元素开始,依次计算每个位置的部分匹配值: - 如果当前位置的字符与前一个位置的部分匹配值对应的字符相等,则部分匹配值加1。 - 如果不相等,则需要回溯到前一个位置的部分匹配值对应的字符的部分匹配值,继续比较。 - 在主串中从左到右依次比较字符,同时在模式串中根据部分匹配表进行跳跃。 - 如果当前字符匹配成功,则继续比较下一个字符。 - 如果当前字符匹配失败,则根据部分匹配表找到模式串中需要跳跃的位置,继续比较。 下面是一个使用KMP算法进行字符串匹配的示例代码: ```python def kmp_search(text, pattern): n = len(text) m = len(pattern) next = get_next(pattern) i = 0 j = 0 while i < n and j < m: if j == -1 or text[i] == pattern[j]: i += 1 j += 1 else: j = next[j] if j == m: return i - j else: return -1 def get_next(pattern): m = len(pattern) next = [-1] * m i = 0 j = -1 while i < m - 1: if j == -1 or pattern[i] == pattern[j]: i += 1 j += 1 next[i] = j else: j = next[j] return next ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值