当前位置: 首页 > article >正文

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

目录

1.实现strStr

2. 重复的子字符串 


1.实现strStr

解法一:暴力匹配(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. 重复的子字符串 

解法一:KMP算法

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

Next数组不减一,不移动的做法
注释详细请看代码
强烈建议大家把next数组打印出来,看看next数组里的规律,有助于理解KMP算法

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

 

//求字符串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;
}


 

 

 

http://www.lryc.cn/news/2417622.html

相关文章:

  • vue-必备知识点,图文详解
  • VSCode初级使用教程详细版
  • 科技概念/名词解释
  • 计算机毕设ssm基于BS的高校学生毕业去向管理系统的设计与实现3l47e9(源码+数据库+LW)
  • 多吉搜索不能用了_百度搜索骚技巧,瞬间找到你想要的资源
  • 关于调用静态链接库LIB,提示重定义或库冲突的错误
  • saltstack-redhat6.5版本
  • 难倒了N个硕士和博士的三年级奥数题
  • 博客(Blog)的商业价值实现模式探讨
  • 使用hydra离线破解windows密码
  • 在Windows中使用TCP端口139和445
  • InfoQ-China发布在即,敬请关注支持
  • HttpServletRequest和ServletRequest的区别以及HttpServletRequest对象方法的用法
  • 【Consul】Consul的Linux之旅:实现高效部署与维护的入门指南
  • 华为荣耀5a是android几,荣耀5A配置怎么样 荣耀畅玩5A参数详情
  • vSphere 性能优化方法 故障排错方法及工具总结(一)
  • 抖音垂直养号,关键词养号,autojs脚本自动
  • 一些医学网站
  • Loadrunner中对中文进行UTF-8转码
  • 【论文合集】Awesome Diffusion Models 2
  • 视频编码标准H.264/AVC
  • python 天天向上续以七天为周期_《天天向上》主持人高天鹤回应考试作弊后续:以后要靠自己去拼搏...
  • 渗透测试知识点总结(非常详细),从零基础入门到精通,看完这一篇就够了
  • 分享一些好用的网站
  • MATLAB算法实战应用案例精讲-【人工智能】时空人工智能(Spatio-TemporalAI)(概念篇)
  • python交易是什么意思_py交易是什么意思 py交易是什么梗
  • 生产管理ERP系统应用案例图
  • 如何快速搭建一个免费的 鉴黄 平台?
  • 2022考研计算机-数据库原理教程1-7章
  • 最最详细的黑马前端HTML5+CSS3笔记,给大家整理好了