算法笔记(一)—— KMP算法练习题

简介: 算法笔记(一)—— KMP算法练习题

1.实现strStr


image.png

解法一:暴力匹配(BF)算法

int strStr(char * haystack, char * needle){
    assert(haystack!=NULL&&needle!=NULL);
    int len1=strlen(haystack);
    int len2=strlen(needle);
    int i=0,j=0;
    if(len2==0)
    {
        return 0;
    }
    if(len1==0&&len2!=0)
    {
        return -1;
    }
    while(i<len1&&j<len2)
    {
      if(haystack[i]==needle[j])
      {
          i++;
          j++;
      }
      else{
          i=i-j+1;
          j=0;
      }
    }
    if(j>=len2)
    {
        return i-j;
    }
    else{
        return -1;
    }
}

解法二:KMP算法

int strStr(char * haystack, char * needle){
    if(needle[0]=='\0')
    return 0;
      int len1=(int)strlen(haystack);
      int len2=(int)strlen(needle);
      int i=0;
      int j=0;
      int ans=-1;
      int* next=(int*)malloc(sizeof(int)*len2);
      getnext(next,needle);
      while(i<len1)
      {
          if(j==-1||haystack[i]==needle[j])
          {
             ++i;
              ++j;
          }
          else{
              j=next[j];
          }
          if(j==len2)
      {
          ans=i-len2;
          break;
      }
      }
          return ans;
}
void getnext(int next[],char* needle)
{
    next[0]=-1;
    int j=0;
    int k=-1;
    int len=(int)strlen(needle);
    while(j<len-1)
    {
        if(k==-1||needle[j]==needle[k])
        {
            ++j;
            ++k;
            next[j]=k;
        }
        else{
            k=next[k];
        }
    }
}

解法1和解法2的相关知识点如果有不懂的,可以看下这篇博客有详细讲解:

>>>KMP算法详解

解法三:哈希加速暴力

class Solution {
public:
    int strStr(string haystack, string needle) {
        if(needle=="") return 0;
        int n = haystack.size(), m = needle.size();
        int hash = 0;
        for(auto c: needle){
            hash += c -'a';
        }
        int cur = 0;
        for(int i = 0; i < n; i++){
            cur += haystack[i] - 'a';
            if(i >= m ) cur -= haystack[i-m] - 'a';
            if(i >= m-1 && cur == hash && haystack.substr(i-m+1,m) == needle)
                return i-m+1;
        }
        return -1;
    }
};

解法四:


解题思路

1.定义两个指针,头指针从haystack数组的头开始,尾指针的位置由needle数组的长度确定,也就是(0+len2-1)

2.进入while循环,循环结束的条件是尾指针到达haystack数组的尾部

3.判断haystack数组以head为开头,len2为长度的子串和needle数组是否相同,是则返回此时的head值

4.对头尾两个指针做++操作,保持窗口大小

5.循环结束,代表匹配失败,返回-1

class Solution {
public:
    int strStr(string haystack, string needle) {
        int len1=haystack.size(),len2=needle.size();
        //尾指针的位置由needle数组的长度确定,也就是(0+len2-1)
        int head=0,tail=len2-1;
        //循环结束的条件是尾指针到达haystack数组的尾部
        while(tail<len1){
            //判断haystack数组以head为开头,len2为长度的子串和needle数组是否相同
            if(haystack.substr(head,len2)==needle) return head;
            head++;
            tail++;
        }
        return -1;
    }
};

解法五:C++库函数的运用

class Solution {
class Solution {
public:
    int strStr(string haystack, string needle) {
        if(needle.empty())
            return 0;
        int pos=haystack.find(needle);
        return pos;
    }
};

本题应该还有很多解法,有想到的伙伴们可以评论区留言共同讨论.

2. 重复的子字符串


image.png

解法一:KMP算法

以下是我在力扣发现的一种比较好理解的KMP解法

Next数组不减一,不移动的做法

注释详细请看代码

强烈建议大家把next数组打印出来,看看next数组里的规律,有助于理解KMP算法


最后的if判断可以这样理解:

如果答案是 true 的话,next 表前几位(子字符串)都是 0,后边将是一直递增,next(n-1)存放的就是原字符串减去子字符串长度的值 ,记为len2,将 len-len2的值记为len1,len1它就是子字符串的长度,一定是可以被 len 整除的!

image.png

//求字符串s的next数组
void Getnext(int *next, char *s, int len)
{
    int j=0;
    next[0]=0;
    for(int i=1; i<len; i++)
    {
        while(j>0 && s[i]!=s[j])
        {
            j=next[j-1];
        }
        if(s[i] == s[j])
        {
            j++;
        }
        next[i]=j;
    }
}
bool repeatedSubstringPattern(char * s)
{
    int len = strlen(s);
    if(len == 0) return false;
    int *next = (int*)malloc(sizeof(int) * len);
    Getnext(next, s, len);
    // next[len-1]!=0 代表s字符串有最长的相等前后缀
    // len % (len - next[len-1]) == 0 
    // 代表(数组长度 - 最长相等前后缀的长度)正好可以被数组的长度整除
    if(next[len-1]!=0 && len % (len - next[len-1]) == 0)
    {
        return true;
    }
    return false;
}

解法二:枚举法

思路与算法

如果一个长度为 nn 的字符串 ss 可以由它的一个长度为 n'n   的子串 s's ′重复多次构成,那么:nn 一定是 n'n ′  的倍数;s's ′一定是 ss 的前缀;对于任意的 i \in [n', n)i∈[n ′ ,n),有 s[i] = s[i-n']s[i]=s[i−n ′ ]。也就是说,ss 中长度为 n'n ′  的前缀就是 s's ′ ,并且在这之后的每一个位置上的字符 s[i]s[i],都需要与它之前的第 n'n ′  个字符 s[i-n']s[i−n ′ ] 相同。因此,我们可以从小到大枚举 n'n ′ ,并对字符串 ss 进行遍历,进行上述的判断。注意到一个小优化是,因为子串至少需要重复一次,所以 n'n ′  不会大于 nn 的一半,我们只需要在 [1, \frac{n}{2}][1, 2n ] 的范围内枚举 n'n ′即可。

bool repeatedSubstringPattern(char * s){
    int len=strlen(s);
   for(int i=1;i*2<=len;i++)
   {
       if(len%i==0){
       bool match=true;
       for(int j=i;j<len;j++)
       {
           if(s[j]==s[j-i])
           {
            match=true;
           }
           else{
               match=false;
               break;
           }
       }
       if(match==true)
       {
           return true;
       }
   }
   }
       return false;
}

解法三:字符串匹配

bool repeatedSubstringPattern(char* s) {
    int n = strlen(s);
    char k[2 * n + 1];
    k[0] = 0;
    strcat(k, s);
    strcat(k, s);
    return strstr(k + 1, s) - k != n;
}
相关文章
|
3月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
80 1
|
3月前
|
算法 索引
❤️算法笔记❤️-(每日一刷-141、环形链表)
❤️算法笔记❤️-(每日一刷-141、环形链表)
53 0
|
3月前
|
算法
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
54 0
|
3月前
|
算法
【❤️算法笔记❤️】-每日一刷-23、合并 K 个升序链表
【❤️算法笔记❤️】-每日一刷-23、合并 K 个升序链表
36 0
|
3月前
|
存储 算法
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
116 0
|
3月前
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
91 1
|
3月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
81 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
3月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
20 1
|
3月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
23 0
|
3月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
35 0

热门文章

最新文章