今天的两道题关键在于学习KMP算法。KMP算法运用场景在于一串字符串里面查找是否含有某个子字符串,如“abcdef”里面就含有“cdf”这么个子字符串。先把题目作完,后面附上KMP算法的一些介绍。

28. 找出字符串中第一个匹配项的下标

这就是典型的匹配和找子字符串的题目。解答如下:

class Solution {public int strStr(String haystack, String needle) {int h = haystack.length();int n = needle.length();int [] nextNum = new int[n];if(n == 0){  //特殊情况,直接返回0return 0;}for(int i = 1,j = 0; i < n - 1; i++){ //生成next数组while(j > 0 && needle.charAt(j) != needle.charAt(i)){j = nextNum[j - 1];}if(needle.charAt(j) == needle.charAt(i)){j++;}nextNum[i] = j;}for(int i = 0, j = 0; i < h; i++){  //开始遍历寻找是否有子字符串while(j > 0 && needle.charAt(j) != haystack.charAt(i)){j = nextNum[j - 1];}if(needle.charAt(j) == haystack.charAt(i)){j++;}if(j == n){return i - n + 1;}}return -1;}
}

459. 重复的子字符串

这里用暴力法遍历是可以求解出来的,也可以使用KMP算法,关键在于有一个推论,知道后才能使用。

假设字符串s是由s1+s2组成的,s+s后,str就变成了s1+s2+s1+s2,去掉首尾,破环了首尾的s1和s2,变成了s3+s2+s1+s4,此时str中间就是s2+s1,如果s是循环字串,也就是s1=s2,所以str中间的s2+s1就和原字符串相等。如果s不是循环字串,s1!=s2,那么s1+s2是不等于s2+s1的,也就是str中间不包含s。其中s2是可以等于N*s1的,比如:“ababab”,s1=“ab”,s2=“abab”,也是成立的。

利用这个推论,题目就可以看成在两个s相加并去掉首位字符后,能不能在里面找到子字符串s,如果可以,说明是重复的,如果不行,则不重复。

class Solution {public boolean repeatedSubstringPattern(String s) {String t = s + s;int len = s.length();int [] nextNum = new int [len];for(int i = 1, j = 0; i < len; i++){ //先给出next数组while(j > 0 && s.charAt(i) != s.charAt(j)){j = nextNum[j - 1];}if(s.charAt(i) == s.charAt(j)){j++;}nextNum[i] = j;}for(int i = 1, j = 0; i < t.length() - 1; i++){ //查找s+s去头去尾中是否含有子字符串s。//i从1开始也就是去头,t.length() - 1去尾while(j > 0 && t.charAt(i) != s.charAt(j) ){j = nextNum[j - 1];}if(t.charAt(i) == s.charAt(j)){j++;}if(j == len){return true;}}  return false; }
}

KMP算法我觉得力扣解题中的宫水三叶讲得挺清晰的。【宫水三叶】简单题学 KMP 算法

朴素解法

直观的解法的是:枚举原串 ss 中的每个字符作为「发起点」,每次从原串的「发起点」和匹配串的「首位」开始尝试匹配:

匹配成功:返回本次匹配的原串「发起点」。

匹配失败:枚举原串的下一个「发起点」,重新尝试匹配。

代码:

Java

C++

class Solution {

public int strStr(String ss, String pp) {

int n = ss.length(), m = pp.length();

char[] s = ss.toCharArray(), p = pp.toCharArray();

// 枚举原串的「发起点」

for (int i = 0; i <= n - m; i++) {

// 从原串的「发起点」和匹配串的「首位」开始,尝试匹配

int a = i, b = 0;

while (b < m && s[a] == p[b]) {

a++;

b++;

}

// 如果能够完全匹配,返回原串的「发起点」下标

if (b == m) return i;

}

return -1;

}

}

时间复杂度:n 为原串的长度,m 为匹配串的长度。其中枚举的复杂度为 O(n−m)O(n - m)O(n−m),构造和比较字符串的复杂度为 O(m)O(m)O(m)。整体复杂度为 O((n−m)∗m)O((n - m) * m)O((n−m)∗m)。

空间复杂度:O(1)。

KMP 解法

KMP 算法是一个快速查找匹配串的算法,它的作用其实就是本题问题:如何快速在「原字符串」中找到「匹配字符串」。

上述的朴素解法,不考虑剪枝的话复杂度是 O(m∗n)O(m * n)O(m∗n) 的,而 KMP 算法的复杂度为 O(m+n)O(m + n)O(m+n)。

KMP 之所以能够在 O(m+n)O(m + n)O(m+n) 复杂度内完成查找,是因为其能在「非完全匹配」的过程中提取到有效信息进行复用,以减少「重复匹配」的消耗。

你可能不太理解,没关系,我们可以通过举

随想录Day9--28. 实现 strStr() , 459.重复的子字符串相关推荐

  1. 【代码随想录二刷】day9 | 28. 实现 strStr() 459.重复的子字符串

    二刷主要记录理解不一样的题 一刷地址:day9 今日题目:中等 KMP:困难 => 第一时间想到了使用KMP,但是不太会,只有用常规方法完成 实现 strStr():拼接完两个字符串s之后,取其 ...

  2. 代码随想录day9|实现strStr()、重复的子字符串

    实现strStr() 一般的字符串匹配问题我们可以使用KMP算法来处理,当我们搜索文本串和模式串是否匹配的时候,我们先得到模式串的一个前缀表,其中前缀表中存放的内容是模式串的最长相等前后缀.例如文本串 ...

  3. 代码随想录Day09:28. 实现 strStr()、459.重复的子字符串、字符串总结 、双指针回顾

    目录 Day09:28. 实现 strStr().459.重复的子字符串.字符串总结 .双指针回顾 28. 实现 strStr() (一刷只看了思想) 459.重复的子字符串 (本题一刷跳过了) 字符 ...

  4. 402-字符串(题目:剑指Offer58-II.左旋转字符串、 28. 实现 strStr()、459.重复的子字符串)

    题目:剑指Offer58-II.左旋转字符串 class Solution {public:string reverseLeftWords(string s, int n) {string s1(s. ...

  5. 算法Day8|字符串专题二 剑指 Offer 58 - II. 左旋转字符串,28. 找出字符串中第一个匹配项的下标,459. 重复的子字符串

    剑指 Offer 58 - II. 左旋转字符串 解题思路: 反转区间为前n的子串 反转区间为n到末尾的子串 反转整个字符串 class Solution {public String reverse ...

  6. js实现kmp算法_「leetcode」459.重复的子字符串:KMP算法还能干这个!

    不瞒你说,重复子串问题,KMP很拿手 题目459.重复的子字符串 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且长度不超过10000. 示例 1: ...

  7. 字符串专题-LeetCode:剑指 Offer 58 - II. 左旋转字符串、LeetCode 459.重复的子字符串、 代码思路和注意点

    文章目录 一.剑指 Offer 58 - II. 左旋转字符串 二.LeetCode 459.重复的子字符串 一.剑指 Offer 58 - II. 左旋转字符串 思路: 预留出n个字符空间s.res ...

  8. 459. 重复的子字符串-KMP算法

    459. 重复的子字符串 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成. 示例 1: 输入: s = "abab" 输出: true 解释: 可由子串 & ...

  9. 力扣459. 重复的子字符串(KMP,JavaScript)

    如果 next[len - 1] != 0,则说明字符串有最长相同的前后缀(就是字符串里的前缀子串和后缀子串相同的最长长度). 最长相等前后缀的长度为:next[len - 1] . 数组长度为:le ...

最新文章

  1. Ubuntu 安装 CUDA 和 cuDNN 详细步骤
  2. ajax传递数组 php,jQuery.ajax向后台传递数组问题如何解决
  3. python【蓝桥杯vip练习题库】ADV-351比大小
  4. SmartWeatherAPI C#版
  5. 洛谷 1072 Hankson 的趣味题——质因数界限讨论
  6. 通过日志恢复MSSQL数据案例
  7. TP的门面Facade:静态方式调用方法
  8. 剑与远征新海盗版本10章怎么去过?Boss也会随着章节、等级提升
  9. ROBOTS.TXT屏蔽笔记、代码、示例大全
  10. 神经网络Neural Net背景介绍
  11. java值传递和引用传递的例子,Java中的值传递和引用传递实例介绍
  12. 老罗将死,或者Android也将就换代,但是互联网的,共享,互助精神将永存
  13. docker命令总结(二)
  14. ANDROID cmake版本下载,android studio中为gradle指定cmake版本
  15. Java中this和super关键字分别是什么意思
  16. wpa_supplicant 的使用
  17. 小刘的http状态码整理
  18. win7 linux 虚拟机共享文件夹,Win7主机和虚拟机Linux Virtualbox共享文件夹设置教程...
  19. Unity应该怎样学习
  20. 计算机主机内的零件有什么用,ROM和RAM分别是什么?有什么区别?与电脑的什么配件的作用是一? 爱问知识人...

热门文章

  1. 人为什么要学会思考(学习)?
  2. Gopher China 大会福利加码
  3. 通达oa mysql 登陆_通达oa 怎么进入mysql?
  4. 基于H5+Android的高校自动排课APP系统
  5. 中国的银行简称新解,笑死人!
  6. 《Deep Neural Networks for YouTube Recommendation》译读
  7. Stack Overflow 最火的一段代码竟然有 Bug...
  8. php mysql 男女_PHP-MySQL插入与选择
  9. 专利申请与专利转让有什么区别?
  10. 2021/01/03 新标日第1课