【五十三】【算法分析与设计】1392. 最长快乐前缀,686. 重复叠加字符串匹配,796. 旋转字符串,KMP算法

目录

1392. 最长快乐前缀

思路

过程

686. 重复叠加字符串匹配

796. 旋转字符串

string内置函数find

KMP算法

结尾


 

1392. 最长快乐前缀

「快乐前缀」 是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。

给你一个字符串 s,请你返回它的 最长快乐前缀。如果不存在满足题意的前缀,则返回一个空字符串 ""

示例 1:

输入:s = "level" 输出:"l" 解释:不包括 s 自己,一共有 4 个前缀("l", "le", "lev", "leve")和 4 个后缀("l", "el", "vel", "evel")。最长的既是前缀也是后缀的字符串是 "l" 。

示例 2:

输入:s = "ababab" 输出:"abab" 解释:"abab" 是最长的既是前缀也是后缀的字符串。题目允许前后缀在原字符串中重叠。

提示:

  • 1 <= s.length <= 10(5)

  • s 只含有小写英文字母

思路

这道题目的意思是,给我们一个字符串s,需要我们返回这个字符串s的最长公共前后缀的长度。

计算某一个字符串s的最长公共前后缀的长度,依靠kmp算法中计算match模式串next数组的计算方式即可。

首先创建一个next数组,next[i]表示0~i-1区间的最长公共前后缀长度。

因此next数组的长度应该为s.size()+1,因为我们需要得到0~s.size()-1区间的最长公共前后缀长度。

对应是next[s.size()],所以next的大小选哟是s.size()+1。

过程

1. if (next.size() == 1) return ""; kmp计算next数组,一定不要忘记next数组长度为1的时候直接返回。

因为next数组中,next[0]=-1,next[1]=0,这两个位置是人为定义的,因此为了不能越界访问,当next长度为1的时候,直接返回。

2. next[0] = -1, next[1] = 0; int i = 2; int cn = 0;

初始化,从i=2位置开始填写next数组。对于每一个新的i,cn一定是next[i-1]的值。

3. while (i < next.size()) { if (s[cn] == s[i - 1]) { next[i] = cn + 1; i++, cn = cn + 1;

while循环,黑盒,内部逻辑将i位置的next计算完毕。

4.

如果s[cn]==s[i-1],此时next[i]=cn+1。

填写好next[i],维护下一个i和cn的值。

i++,cn=cn+1。

5. } else if (cn != 0) { cn = next[cn];

如果s[cn]!=s[i-1],此时cn=next[cn],继续判断s[cn]与s[i-1]。

6. } else { next[i] = 0; i++, cn = 0;

如果cn==0,对应的next[cn]=-1,此时next[i]=0。

维护下一个i和cn。

i++,cn=0。 7. return s.substr(0, next[s.size()]); 返回next[s.size()],表示0~s.size()区间长度的最长公共前后缀。

 
class Solution {
public:
    string longestPrefix(string s) {
        vector<int> next(s.size() + 1);
        if (next.size() == 1)
            return "";

        next[0] = -1, next[1] = 0;
        int i = 2;
        int cn = 0;
        while (i < next.size()) {
            if (s[cn] == s[i - 1]) {
                next[i] = cn + 1;
                i++, cn = cn + 1;
            } else if (cn != 0) {
                cn = next[cn];
            } else {
                next[i] = 0;
                i++, cn = 0;
            }
        }
        return s.substr(0, next[s.size()]);
    }
};

686. 重复叠加字符串匹配

给定两个字符串 ab,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1

注意:字符串 "abc" 重复叠加 0 次是 "",重复叠加 1 次是 "abc",重复叠加 2 次是 "abcabc"

示例 1:

输入:a = "abcd", b = "cdabcdab" 输出:3 解释:a 重复叠加三遍后为 "abcdabcdabcd", 此时 b 是其子串。

示例 2:

输入:a = "a", b = "aa" 输出:2

示例 3:

输入:a = "a", b = "a" 输出:1

示例 4:

输入:a = "abc", b = "wxyz" 输出:-1

提示:

  • 1 <= a.length <= 10(4)

  • 1 <= b.length <= 10(4)

  • ab 由小写英文字母组成

1.

首先让a不断进行叠加操作,语句是a+=a。

直到a的长度an>=原先a的长度+bn。

因为重复叠加a字符串,b如果是a的子串,开始匹配的位置一定是原先a字符串中某一个字符。

因此可以确定叠加字符串的上界。

2.

如何计算花费了多少个a字符串叠加?

综上所述,a的叠加数等于(len-1)/an+2=(bn-cd-1)/an+2=(bn-(an-(x-y))-1)/an+2=(bn-an+(x-y)-1)/an+2。

3.

利用KMP算法计算a叠加串中b子串开始位置。

 
class Solution {
public:
    int repeatedStringMatch(string a, string b) {
        int maxlen = a.size() + b.size();
        int an = a.size();
        int bn = b.size();
        while (a.size() < maxlen)
            a += a;

        vector<int> next = getNext(b);
        int x = 0, y = 0;
        while (x < a.size() && y < b.size()) {
            if (a[x] == b[y]) {
                x++, y++;
            } else if (y != 0) {
                y = next[y];
            } else {
                x++;
            }
        }

        if (an - (x - y) >= bn) {
            return 1;
        }
        if (y == b.size()) {
            return (bn + x - y - an - 1) / an + 2;
        } else {
            return -1;
        }
    }

    vector<int> getNext(string match) {
        vector<int> next(match.size());
        if (match.size() == 1)
            return {-1};
        next[0] = -1, next[1] = 0;
        int i = 2;
        int cn = 0;
        while (i < next.size()) {
            if (match[cn] == match[i - 1]) {
                next[i] = cn + 1;
                i++;
                cn = cn + 1;
            } else if (cn != 0) {
                cn = next[cn];
            } else {
                next[i] = 0;
                i++;
                cn = 0;
            }
        }
        return next;
    }
};

796. 旋转字符串

给定两个字符串, sgoal。如果在若干次旋转操作之后,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

  • sgoal 由小写英文字母组成

string内置函数find

1.

两个a字符串叠加在一起,叠加后的字符串寻找模式串goal,看是否能在叠加后的字符串子串找到模式串。

2.

利用string内置函数find寻找子串开始匹配位置。

 
class Solution {
public:
    bool rotateString(string s, string goal) {
        if(s.size()!=goal.size()) return false;
        s+=s;
        int pos=s.find(goal);
        if(pos==-1) return false;
        else return true;
    }
};

KMP算法

 
class Solution {
public:
    bool rotateString(string s, string goal) {
        if(s.size()!=goal.size()) return false;
        s+=s;
        vector<int> next=getNext(goal);
        int x=0,y=0;
        while(x<s.size()&&y<goal.size()){
            if(s[x]==goal[y]){
                x++,y++;
            }else if(y!=0){
                y=next[y];
            }else{
                x++;
            }
        }

        if(y==goal.size()) return true;
        else return false;
    }

    vector<int> getNext(string match){
        if(match.size()==1) return {-1};
        vector<int> next(match.size());
        next[0]=-1;
        next[1]=0;
        int i=2;
        int cn=0;
        while(i<next.size()){
            if(match[cn]==match[i-1]){
                next[i]=cn+1;
                i++,cn=cn+1;
            }else if(cn!=0){
                cn=next[cn];
                
            }else{
                next[i]=0;
                i++,cn=0;
            }
        }

        return next;
    }
};

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/548823.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA_类和对象(1)

认识面向对象 Java是一门纯面向对象的语言(Object Oriented Program, OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情。  面向过程和面相对象并不是一门语言&#xff0c;而是解决…

OpenStack镜像管理与制作

一、OpenStack镜像服务 1、什么是镜像 镜像通常是指一系列文件或一个磁盘驱动器的精确副本。虚拟机所使用的虚拟磁盘&#xff0c;实际上是一种特殊格式的镜像文件。云环境下尤其需要镜像。镜像就是一个模板&#xff0c;类似于VMware的虚拟机模板&#xff0c;其预先安装基本的…

格雷希尔G80L-T系列大口径快速连接器,在汽车膨胀水箱的气密性测试密封方案

副水箱也有人称作膨胀水箱&#xff0c;是汽车散热系统的一个重要组成部分&#xff0c;当水箱里面的温度过高的时候就会产生一定的压力&#xff0c;而副水箱可以根据热胀冷缩来帮助水箱和发动机排出去多余的水&#xff0c;起到一个调节的作用&#xff0c;副水箱由PP/PE塑料注塑而…

单向链表的实现

前言&#xff1a;继顺序表后的又一个线性结构——链表&#xff0c;这里将单向链表的实现。 目录 链表简介: 多文件实现&#xff1a; SList.h&#xff1a; SList.c实现函数的详解&#xff1a; 因为插入数据需要创建节点&#xff0c;很频繁&#xff0c;所以直接将创建新节点分…

《中医病证分类与代码》-中医疾病分类数据库

《中医病症分类与代码》由国家中医药管理局2020年底修订&#xff0c;目的是为中医疾病及证候的分类提供统一的规范。规定2021年起&#xff0c;各中医机构的临床科室及基层中医药的医师都应按照最新修订的《中医病症分类与代码》规范来填报病案及病历。 中医病证分类与代码数据库…

C++STL详解(一)— string类

string 类对象的常见容量操作 函数名称 功能 size 返回字符串有效字符长度length返回字符串有效字符长度capacity返回空间总大小clear清空有效字符empty检测字符串是否为空串&#xff0c;是返回true,否则返回falsereserve对容量进行改变resize扩容初始化 size和length 文档解…

Linux系统(centos,redhat,龙芯,麒麟等)忘记密码,怎么重置密码

Linux系统&#xff08;centos,redhat,龙芯&#xff0c;麒麟等&#xff09;忘记密码&#xff0c;怎么重置密码&#xff0c;怎么设置新的密码 今天在操作服务器时&#xff0c;DBA忘记了人大金仓数据库的kingbase密码&#xff0c;他的密码试了好多遍&#xff0c;都不行。最后只能…

sublime text中文---功能强大、操作便捷的代码编辑神器

Sublime Text是一款极受欢迎的代码编辑器&#xff0c;以其出色的性能、丰富的功能和优雅的用户界面赢得了广大开发者的青睐。它支持多种编程语言&#xff0c;包括HTML、CSS、JavaScript、Python等&#xff0c;让开发者能够轻松编辑和调试各种代码。Sublime Text拥有强大的自定义…

配置路由器实现互通

1.实验环境 实验用具包括两台路由器(或交换机)&#xff0c;一根双绞线缆&#xff0c;一台PC&#xff0c;一条Console 线缆。 2.需求描述 如图6.14 所示&#xff0c;将两台路由器的F0/0 接口相连&#xff0c;通过一台PC 连接设备的 Console 端口并配置P地址&#xff08;192.1…

SpringBoot是如何实现main方法启动Web项目的?

一、问题解析 在Spring Boot中&#xff0c;通过SpringApplication类的静态方法run来启动Web项目。当我们在main方法中调用run方法时&#xff0c;Spring Boot使用一个内嵌的Tomcat服务器&#xff0c;并将其配置为处理Web请求。 当应用程序启动时&#xff0c;Spring Boot会自动扫…

C#学习笔记11:winform上位机与西门子PLC网口通信_下篇

今日终于到了winform上位机与西门子PLC网口通信的系列收为阶段了&#xff0c;一直没一口气更新完&#xff0c;手头上也没有可以测试用的PLC设备&#xff0c;虚拟仿真用到的博图软件也不想下载&#xff08;会让我电脑变卡&#xff09;。 于是等了些日子购买西门子PLC&#xff0…

JIT在汽车行业中的革命性应用:颠覆传统制造模式,引领智能制造新时代

随着科技的飞速发展和市场竞争的日益激烈&#xff0c;汽车行业正面临着前所未有的变革。其中&#xff0c;准时制生产&#xff08;Just-In-Time&#xff0c;简称JIT&#xff09;作为一种先进的生产管理方式&#xff0c;已经在汽车行业中得到了广泛应用&#xff0c;成为推动汽车产…

密码学 | 椭圆曲线 ECC 密码学入门(三)

目录 7 这一切意味着什么&#xff1f; 8 椭圆曲线密码学的应用 9 椭圆曲线密码学的缺点 10 展望未来 ⚠️ 原文地址&#xff1a;A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography ⚠️ 写在前面&#xff1a;本文属搬运博客&#xff0c;自己留…

论文略读:Window Attention is Bugged: How not to Interpolate Position Embeddings

iclr 2024 reviewer 打分 6666 窗口注意力、位置嵌入以及高分辨率微调是现代Transformer X CV 时代的核心概念。论文发现&#xff0c;将这些几乎无处不在的组件简单地结合在一起&#xff0c;可能会对性能产生不利影响问题很简单&#xff1a;在使用窗口注意力时对位置嵌入进行插…

DC-1渗透测试复现

DC-1渗透测试复现 目的&#xff1a; 获取最高权限以及5个flag 过程&#xff1a; 信息打点-cms框架漏洞利用-数据库-登入admin-提权 环境&#xff1a; 攻击机&#xff1a;kali(192.168.85.136) 靶机&#xff1a;DC_1(192.168.85.131) 复现&#xff1a; 一.信息收集 扫…

IDEA 本地库引入了依赖但编译时找不到

在使用 IDEA 开发 Maven 项目的过程中&#xff0c;有时会遇到本地库引入了依赖&#xff0c;但编译时报找不到这个依赖&#xff0c;可以使用命令处理。 打开 Terminal。 执行清理命令。 mvn clean install -Dmaven.test.skiptrue执行更新命令。 mvn -U idea:idea

怎么清除3D模型杂质?---模大狮模型网

在进行3D建模过程中&#xff0c;模型可能会受到各种杂质的影响&#xff0c;这些杂质可能来自于模型本身的结构问题、导入导出过程中的错误、或者是不当的编辑操作所留下的痕迹。清除这些杂质是保证模型质量和渲染效果的关键步骤之一。本文将介绍几种常见的清除3D模型杂质的方法…

【C++】适配器· 优先级队列 仿函数 反向迭代器

目录 适配器&#xff1a;适配器的应用&#xff1a;1. 优先级队列&#xff1a;仿函数&#xff1a;更深入的了解仿函数&#xff1a;一个关于不容易被注意的知识点&#xff1a; 2. 反向迭代器&#xff1a;list && vector&#xff1a; 适配器&#xff1a; 我们先来谈来一下…

最新IntelliJ IDEA 2024.1 安装和快速配置教程

IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版 文章目录 IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版前言 第一步&#xff1a; IntelliJ IDEA 2024.1安装教程第 0 步&…

activiti初次学习

源代码地址&#xff1a;https://gitee.com/ZSXYX/activiti.git​ 1、安装插件 首先安装下图所示activiti,不确定是哪个插件有用的&#xff0c;有时间可排除下 在resources下创建一个文件夹&#xff1a;processes,右键&#xff0c;新建 生成&#xff1a; 选中act.bpmn20.xm…