首页 > 其他分享 >【LeetCode字符串#extra】KMP巩固练习:旋转字符串、字符串轮转

【LeetCode字符串#extra】KMP巩固练习:旋转字符串、字符串轮转

时间:2023-05-14 22:27:28浏览次数:54  
标签:goal extra s2 next KMP 字符串 size string

旋转字符串

https://leetcode.cn/problems/rotate-string/

给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。

s 的 旋转操作 就是将 s 最左边的字符移动到最右边。

例如, 若 s = 'abcde',在旋转一次之后结果就是'bcdea' 。

示例 1:

输入: s = "abcde", goal = "cdeab"
输出: true

示例 2:

输入: s = "abcde", goal = "abced"
输出: false

提示:

1 <= s.length, goal.length <= 100
s 和 goal 由小写英文字母组成

思路

与重复子串一样有两种思路:

1、直接将字符串s和goal相加,然后再相加后的字符串中查找s或者goal,找到就可以返回true

2、使用KMP算法

先求出s的next数组,然后还是将字符串s和goal相加,得到新字符串

goal 字符串复制一份连接到自身末尾,得到新的字符串 s2 的目的是为了模拟旋转操作之后的字符串。

假设原始字符串是 s,通过左旋若干次后得到的新字符串是 s'。如果我们将 ss' 进行比较,就会发现它们实际上是相同的字符串,只是从不同位置开始截取的。而这个位置的关系可以通过将 goal 复制一份连接到自身末尾来体现。

举个例子:假设 s = "abcde",将 s 左移两位得到的新字符串是 s' = "cdeab"。那么将 goal 复制一份连接到自身末尾,得到的字符串是 goal + goal = "cdeababcde"。我们可以发现,在 goal + goal 中,第一个 goals' 是对应的,因为它们都是从 c 开始的;第二个 goal 对应的就是 s,因为它们都是从 a 开始的。

使用KMP算法在新字符串中查找s

为了这点醋包了这碗面

代码

字符串相加使用find
//与重复子字符串的简单版本思路类似
class Solution {
public:
    bool rotateString(string s, string goal) {
        return s.size() == goal.size() && (s + s).find(goal) != string::npos;
    }
};
脱裤子放屁法(KMP)
class Solution {
private:
    void getNext(int* next, string& s){
        int j = -1;
        next[0] = j;
        for(int i = 1 ;i < s.size(); ++i){
            while(j >= 0 && s[i] != s[j + 1]) j = next[j];

            if(s[i] == s[j + 1]) j++;
            next[i] = j;
        }
    }
public:
    bool rotateString(string s, string goal) {
        //判断一下,如果两个字符串长度不等直接false,如果给的字符串是空,那怎么转都可以得到本身,返回true
        //s为空goal不空的情况已经包含第一个判断中
        if(s.size() != goal.size()) return false;
        if(s.empty()) return true;

        // 将goal字符串复制一份连接到自身末尾,得到新的字符串s2
        string s2 = goal + goal; //string s2 = s + goal;也行
        int j = -1;
        int next[s.size()];
        getNext(next, s);

        for(int i = 0; i < s2.size(); ++i){//在s2中查找s
            while(j >= 0 && s2[i] != s[j + 1]){
                j = next[j];
            }

            if(s2[i] == s[j + 1]){
                j++;
            }

            if(j == s.size() - 1) return true;//遍历完s后结束
        }
        return false;
    }
};

字符串轮转

https://leetcode.cn/problems/string-rotation-lcci/

字符串轮转。给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottle是erbottlewat旋转后的字符串)。

示例1:

输入:s1 = "waterbottle", s2 = "erbottlewat"
输出:True
示例2:

输入:s1 = "aa", s2 = "aba"
输出:False
提示:

字符串长度在[0, 100000]范围内。
说明:

你能只调用一次检查子串的方法吗?

思路

和旋转字符串一样,直接给代码

代码

字符串相加使用find
//与重复子字符串的简单版本思路类似
class Solution {
public:
    bool isFlipedString(string s1, string s2) {
        return s1.size() == s2.size() && (s2 + s2).find(s1) != string::npos;
    }
};
KMP
//kmp版本
class Solution {
private:
    void getNext(int* next, string& s){
        int j = -1;
        next[0] = j;

        for(int i = 1; i < s.size(); ++i){
            while(j >= 0 && s[j + 1] != s[i]){
                j = next[j];
            }

            if(s[j + 1] == s[i]) j++;
            next[i] = j;
        }

    }
public:
    bool isFlipedString(string s1, string s2) {
        if(s1.size() != s2.size()) return false;
        if(s1.empty()) return true;

        int j = -1;
        int next[s1.size()];
        string ss2 = s2 + s2;
        getNext(next, s1);

        for(int i = 0; i < ss2.size(); ++i){
            while(j >= 0 && ss2[i] != s1[j + 1]) j = next[j];

            if(ss2[i] == s1[j + 1]) j++;

            if(j == s1.size() - 1) return true;
        }
        return false;
    }
};

标签:goal,extra,s2,next,KMP,字符串,size,string
From: https://www.cnblogs.com/DAYceng/p/17400398.html

相关文章

  • LeetCode 1047. 删除字符串中的所有相邻重复项
    题目链接:LeetCode1047.删除字符串中的所有相邻重复项题意:给出由小写字母组成的字符串S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在S上反复执行重复项删除操作,直到无法继续删除。解题思路:开一个栈,然后扫描整个字符串。如果当前字符和栈顶元素不相等,则当前......
  • 【LeetCode数据结构04】字符串String
    TableofContents双指针344.反转字符串541.反转字符串II剑指Offer05.替换空格151.翻转字符串里的单词剑指Offer58-II.左旋转字符串KMP28.实现strStr459.重复的子字符串Solutions344.反转字符串力扣题目链接思路代码541.反转字符串II......
  • Python学习之五_字符串处理生成查询SQL
    Python学习之五_字符串处理生成查询SQL前言昨天想给同事讲解一下获取查询部分表核心列信息的SQL方法也写好了一个简单文档.但是感觉不是很优雅.最近两三天晚上一直在学习Python.想将昨天的文档处理成一个工具的方式.将查询SQL展示出来.然后再由同事手工检查确认.增加时......
  • 把流中的字符串转换为 UTF 格式
    unitUnit1;interfaceuses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms, Dialogs,StdCtrls;type TForm1=class(TForm)  Button1:TButton;  Memo1:TMemo;  procedureButton1Click(Sender:TObject);  pr......
  • 记一次解‘字符串加解密’算法
    题目:对输入的字符串进行加解密,并输出。加密方法为:当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B;字母Z时则替换为a;当内容是数字时则把该数字加1,如0替换1,1替换2,9替换0;其他字符不做变化。解密方法为加密的逆过程。数据范围:输入的......
  • sql server 将datetime类型的字段转化成字符串输出
    SELECTOBJID,NAME,CONVERT(varchar(19),CREATIONDATE,120)ASCREATIONDATEFROM[dbo].[SYS_DOCUMENTREV]WHERENAMELIKE'test%.pdf'ORDERBYCREATIONDATEDESC......
  • bat中传递JSON参数时,由于JSON包含一些特殊字符如引号、反斜杠等,需要对JSON字符串进行
    在bat中传递JSON参数时,由于JSON包含一些特殊字符如引号、反斜杠等,这些字符可能会导致命令行解释器解析出错。为了避免这些问题,通常建议对JSON字符串进行一些转义处理。具体转义规则如下:对每个双引号(")进行转义,变成"。对每个反斜杠(\)进行转义,变成\。当你传递一个JSON字符串......
  • 在C#中使用默认值初始化字符串数组的3种方式
    在本文中,您将学习到新建字符串数组如何设置默认值。数组是可以使用索引访问的相同类型的元素的集合。对于字符串数组,每个元素都是一个字符串值。在C#中创建新的字符串数组时,默认值为null。但是,在某些情况下,您可能希望使用特定的默认值而不是null初始化字符串数组。例如,希望A......
  • 2022-01-30:最小好进制。 对于给定的整数 n, 如果n的k(k>=2)进制数的所有数位全为1,则称 k(k
    2022-01-30:最小好进制。对于给定的整数n,如果n的k(k>=2)进制数的所有数位全为1,则称k(k>=2)是n的一个好进制。以字符串的形式给出n,以字符串的形式返回n的最小好进制。输入:“4681”输出:“8”解释:4681的8进制是11111。提示:n的取值范围是[3,10^18]。输入总是有效且......
  • Delphi 字符串拆分/分割[1] - TStringList
    1、TStringList默认以','拆分字符onstconstr:String='aaa,bbb,ccc,ddd';varstrs:TStrings;i:Integer;beginstrs:=TStringList.Create;strs.CommaText:=constr;fori:=0toStrs.Count-1doShowMessage(Strs[i]);//aaabbbcccd......