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

永康网站优化seo兼职怎么收费

永康网站优化,seo兼职怎么收费,网站建设大概费用,移动端开发平台目录: 解题及思路学习 28. 实现 strStr() https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/ 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下…

目录:

解题及思路学习

28. 实现 strStr()

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

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 ****。

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

思考:字符串匹配,可以直接暴力方法。但是这题肯定是kmp算法。

前缀表:前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。

使用前缀表,就不会从头匹配,而是从上次已经匹配的内容开始匹配,找到了模式串中第三个字符b继续开始匹配。

**前缀表是如何记录的呢?**什么是前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。

前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串

后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串

前缀表要求的就是相同前后缀的长度。

所以字符串a的最长相等前后缀为0。 字符串aa的最长相等前后缀为1。 字符串aaa的最长相等前后缀为2。 等等…。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pXWB2jJR-1691982232460)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/0577fe82-fba0-498e-8995-e7eca0fbc040/Untitled.png)]

前缀表可以告诉我们匹配失败之后跳到哪里重新开始匹配。

下标5之前这部分的字符串(也就是字符串aabaa)的最长相等的前缀 和 后缀字符串是 子字符串aa ,因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面重新匹配就可以了。

如何计算前缀表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mC760OQe-1691982232464)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/87bd2181-9cb1-4836-ad3f-6a2dd4a50f59/Untitled.png)]

可以看出模式串与前缀表对应位置的数字表示的就是:下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。

KMP算法的时间复杂度是O(n+m)的。暴力的解法显而易见是O(n × m),所以KMP在字符串匹配中极大地提高了搜索的效率。

构造next数组

构造next数组其实就是计算模式串s,前缀表的过程。 主要有如下三步:

  1. 初始化
  2. 处理前后缀不相同的情况
  3. 处理前后缀相同的情况

前缀表统一减一的操作

class Solution {
public:void getNext(int* next, const string& s) {int j = -1;next[0] = j;for(int i = 1; i < s.size(); i++) { // 注意i从1开始while (j >= 0 && s[i] != s[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()];getNext(next, needle);int j = -1; // // 因为next数组里记录的起始位置为-1for (int i = 0; i < haystack.size(); i++) { // 注意i就从0开始while(j >= 0 && haystack[i] != needle[j + 1]) { // 不匹配j = next[j]; // j 寻找之前匹配的位置}if (haystack[i] == needle[j + 1]) { // 匹配,j和i同时向后移动j++; // i的增加在for循环里}if (j == (needle.size() - 1) ) { // 文本串s里出现了模式串treturn (i - needle.size() + 1);}}return -1;}
};
  • 时间复杂度: O(n + m)
  • 空间复杂度: O(m), 只需要保存字符串needle的前缀表

前缀表(不减一)C++实现

i表示后缀末尾,ji傲视前缀末尾。

class Solution {
public:void getNext(int* next, const string& s) {int j = 0;next[0] = 0;for(int i = 1; i < s.size(); i++) {while (j > 0 && s[i] != s[j]) {j = next[j - 1];}if (s[i] == s[j]) {j++;}next[i] = j;}}int strStr(string haystack, string needle) {if (needle.size() == 0) {return 0;}int next[needle.size()];getNext(next, needle);int j = 0;//使用next数据,将haystack与needle进行匹配。for (int i = 0; i < haystack.size(); i++) {while(j > 0 && haystack[i] != needle[j]) {j = next[j - 1];}if (haystack[i] == needle[j]) {j++;}if (j == needle.size() ) {  // 文本串s里出现了模式串treturn (i - needle.size() + 1);}}return -1;}
};
  • 时间复杂度: O(n + m)
  • 空间复杂度: O(m)

多自己写几遍,就会理解的更深一点。

459.重复的子字符串

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

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

思考:最多由一半的子串组成。利用kmp算法不断找最小重复子串。

随想录:判断字符串s是否由重复子串组成,只要两个s拼接在一起,里面还出现一个s的话,就说明是由重复子串组成。当然,我们在判断 s + s 拼接的字符串里是否出现一个s的的时候,要刨除 s + s 的首字符和尾字符,这样避免在s+s中搜索出原来的s,我们要搜索的是中间拼接出来的s。

class Solution {
public:bool repeatedSubstringPattern(string s) {string t = s + s;t.erase(t.begin());t.erase(t.end() - 1);if (t.find(s) != std::string::npos) return true;return false;}          
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

kmp思路:

最长相等前后缀不包含的子串就是最小重复子串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7OWiy2H8-1691982232465)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/df6b2f6b-6ed3-441d-9fee-ffe8dbba32ff/Untitled.png)]

数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。

class Solution {
public:void getNext (int* next, const string& s){next[0] = 0;int j = 0;for(int i = 1;i < s.size(); i++){while(j > 0 && s[i] != s[j]) {j = next[j - 1];}if(s[i] == s[j]) {j++;}next[i] = j;}}bool repeatedSubstringPattern (string s) {if (s.size() == 0) {return false;}int next[s.size()];getNext(next, s);int len = s.size();if (next[len - 1] != 0 && len % (len - (next[len - 1] )) == 0) {return true;}return false;}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

字符串总结

1、C语言中,已结束符’\0’ 判断字符串是否结束。C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用’\0’来判断是否结束。

2、那么vector< char > 和 string 又有什么区别呢?其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。所以想处理字符串,我们还是会定义一个string类型。

3、打基础的时候,不要太迷恋于库函数。

4、双指针法在数组,链表和字符串中很常用。其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

5、KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。

复盘总结

个人反思

字符串类类型的题目,往往想法比较简单,但是实现起来并不容易,复杂的字符串题目非常考验对代码的掌控能力。

双指针法是字符串处理的常客。

KMP算法是字符串查找最重要的算法

http://www.khdw.cn/news/60468.html

相关文章:

  • 内嵌百度新闻网站html源码一站式海外推广平台
  • 南山网站开发网站搭建流程
  • 巩义做网站推广青岛seo推广公司
  • 做海报网站各大网址收录查询
  • 114百事通做网站是不是诈骗seo的培训网站哪里好
  • 室内设计联盟邀请码seo网站推广招聘
  • 教育网站建设的雷区百度链接提交收录入口
  • 福州网站建设哪家专业宁波做网站的公司
  • 网站做排名靠前百度百家自媒体平台注册
  • 班级展示网站自媒体平台
  • 2个域名指向同一个网站seo营销方法
  • 网络推广怎样做广西seo搜索引擎优化
  • 杭州久邦电力建设有限公司网站seo怎么做优化计划
  • 韩国美食做视频网站有哪些网站优化排名易下拉效率
  • 视频网站如何做营销策划百度指数如何提升
  • 地方性手机平台微网站下载百度app最新版
  • 建自己的网站做外贸求几个好看的关键词
  • 徐州网站建设案例关键词推广方式
  • 阿里巴巴做网站费用计入电商seo是什么
  • 怎样建设网站后台php视频转码
  • 怎么添加网站后台站长之家域名查询
  • wdlinux 默认网站深圳网站快速排名优化
  • 数字货币交易网站开发怎么做长沙网站推广合作
  • 深圳网站建设科技有限公司郑州专业seo推荐
  • 一般做网站什么价格品牌营销推广策划方案
  • 全立体网站建设佛山做seo推广公司
  • 河南烟草电子商务网站产品设计
  • wordpress page width单页应用seo如何解决
  • 沈阳网站营销独立站seo实操
  • 网站怎么做流量互换北京seo工程师