【代码随想录刷题】Day09 字符串

在这里插入图片描述


28.实现strStr()
459.重复的子字符串

这两道题先了解一下算法原理,不打算细抠,二刷再把java实现代码补上

1.【28】实现strStr()

1.1 题目描述

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

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

示例 2:
输入:haystack = “leetcode”, needle = “leeto”
输出:-1
解释:“leeto” 没有在 “leetcode” 中出现,所以返回 -1 。

提示:

  • 1 <= haystack.length, needle.length <= 104
  • haystack 和 needle 仅由小写英文字符组成

1.2 解题思路 (在一个串中查找是否出现过另一个串,这是KMP的看家本领)

KMP算法相关知识:KMP算法讲解

1.3 java代码实现

  • 时间复杂度: O(n + m)
  • 空间复杂度: O(m), 只需要保存字符串needle的前缀表
class Solution {
    public void getNext(int[] next, String s){
        int j = -1;
        next[0] = j;
        for (int i = 1; i < s.length(); i++){
            while(j >= 0 && s.charAt(i) != s.charAt(j+1)){//前后缀不相同
                j=next[j];//向前回退
            }

            if(s.charAt(i) == s.charAt(j+1)){
                j++;
            }
            next[i] = j;
        }
    }
    public int strStr(String haystack, String needle) {
        if(needle.length()==0){
            return 0;
        }

        int[] next = new int[needle.length()];
        getNext(next, needle);
        int j = -1;//因为next数组里记录的起始位置为-1
        for(int i = 0; i < haystack.length(); i++){//注意i就从0开始
            while(j>=0 && haystack.charAt(i) != needle.charAt(j+1)){//不配
                j = next[j];//j寻找之前匹配的位置
            }
            if(haystack.charAt(i) == needle.charAt(j+1)){//匹配,j和i同时向后移动
                j++;//i的增加在for循环里
            }
            if(j == needle.length()-1){
                return (i-needle.length()+1);//文本串s里出现了模式串t
            }
        }

        return -1;
    }
}


2.【459】重复的子字符串

2.1 题目描述

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

示例 1:
输入: s = “abab”
输出: true
解释: 可由子串 “ab” 重复两次构成。

示例 2:
输入: s = “aba”
输出: false

示例 3:
输入: s = “abcabcabcabc”
输出: true
解释: 可由子串 “abc” 重复四次构成。 (或子串 “abcabc” 重复两次构成。)

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

2.2 解题思路

2.3 java代码实现

3.字符串总结

划重点!!!

双指针法是字符串处理的常客。
KMP算法是字符串查找最重要的算法,但彻底理解KMP并不容易

3.1 什么是字符串

字符串是若干字符组成的有限序列,也可以理解为是一个字符数组

3.2 要不要使用库函数

【建议】

  • 如果题目关键部分直接使用库函数就能解决,建议不要使用库函数
  • 如果库函数仅仅是解题过程中的一小部分,并且你已经清楚这个库函数的内部实现原理的话,可以考虑使用库函数

3.3 双指针法

双指针法在数组、链表和字符串中很常用。

很多数组填充类的问题,都可以预先给数组扩容至带填充后的大小,然后从后向前操作 。

3.4 反转系列

541.反转字符串II中,我们能想到的暴力解法就是:对于每隔2k个字符的前k个的字符,写了一堆逻辑代码或者再写一个计数器,来统计2k,再统计前k个字符

其实当需要固定规律一段一段的去处理字符串的时候,要想想在for循环的表达上做做文章
只要让i += 2k,i每次移动2k就可以了,然后判断是否需要有反转的区间
因为要找的也就是每2*k区间的起点,这样程序会高效很多

151.反转字符串里的单词中要求翻转字符串里的单词,这道题综合考察了字符串的多种操作
这道题目通过先整体反转再局部反转,实现了反转字符串里的单词。

反转字符串还有一个牛逼的用处,就是达到左旋的效果
LCR182.动态口令中,通过先局部反转再整体反转达到了左旋的效果

3.5 KMP

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

KMP的精髓所在就是前缀表,在KMP算法相关知识中讲解了什么是KMP,什么是前缀表,什么时候使用前缀表

前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前后缀

使用KMP可以解决两类经典问题:

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

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

然后针对前缀表到底要不要减一,这其实是不同KMP实现的方式,在KMP算法相关知识中针对之前两个问题,分别给出了两个不同版本的的KMP实现。

其中主要理解j=next[x]这一步最为关键

4.双指针回顾

请看文章:双指针总结篇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值