[C++] LeetCode 214. 最短回文串

2023-11-04

题目

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

示例 1:
输入: "aacecaaa"
输出:"aaacecaaa"

示例 2:
输入:"abcd"
输出:"dcbabcd"

思路解析

这题考虑把字符串s分成s1s2两部分,即s=s1+s2,其中s1为回文串,s2不是回文串,那么构成的最短回文串就是reverse(s2.begin(),s2.end())+s。所以这道题最大的难点就是找出从起始位置开始的最长回文子串。关于最长回文子串的解法可以参考最长回文子串(https://blog.csdn.net/lv1224/article/details/81051875),

方法一

DP做法是要考虑所有可能的回文串,但是这题只需要考虑从起始位置开始的字符串就可以了,所以直接考虑从起始位置开始的所有字符串,判断是否是回文串即可,注意从大往小考虑,如果构成回文串,剩下的就可以不用考虑
代码

class Solution {
public:
    string shortestPalindrome(string s) {        
        int n=s.size(),maxlen=0;
        if(n<=1) return s;
        int r=n-1;
        while(r>0){
            int i=0,j=r;
            while(j>i&&s[i]==s[j]){
                i++;j--;
            }
            if(i>=j) break;
            r--;
        }
        string s1=s.substr(r+1,n-r-1); 
        reverse(s1.begin(),s1.end());
        return s1+s;
    }
};

方法二 中心扩展

直接采用中心扩展来做,会有一个case过不了,这里有一个小技巧。中心点不需要从起始位置开始,也不需要遍历所有的,只要找到最大的就可以停止了。n=s.size(),那么回文串最大就是s本身,所以只需要从n/2的位置开始往左遍历即可,一旦找到从起始位置开始的回文串,就可以停止寻找,得出答案。这样可以减少程序运行时间。

class Solution {
public:
    string shortestPalindrome(string s) {        
        int n=s.size(),maxlen=0;
        if(n<=1) return s;
        //这里会有一个小技巧
        for(int i=n/2;i>=0&&maxlen<=0;i--){
            int r=1;
            while(i-r>=0&&i+r<n&&s[i-r]==s[i+r]) r++;
            if(maxlen<2*r-1&&i-r+1==0)
                maxlen=2*r-1;
            if(i>=n||s[i]!=s[i+1]) continue;
            r=1;
            while(i-1>=0&&i+1+r<n&&s[i-r]==s[i+1+r]) r++;
            if(maxlen<2*r&&i-r+1==0)
                maxlen=2*r;
        }
        string s1=s.substr(maxlen,n-maxlen); 
        reverse(s1.begin(),s1.end());
        return s1+s;
    }
};

方法三 马拉车算法

static const auto __ = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}();

class Solution {
public:
    string shortestPalindrome(string s) {
        int ns=s.size();
        if(ns<=1) return s;
        string tmp(2*ns+1,'*');
        for(int i=0;i<ns;i++) tmp[2*i+1]=s[i];
        int pos=0,curlen=0,n=tmp.size();
        int maxr=0;
        vector<int> slen(n,0);
        for(int i=0;i<n;i++){
            int mi=2*pos-i,r=mi>=0?slen[mi]:0;
            if(i<pos+curlen&&i+r<pos+curlen){
                slen[i]=slen[mi];
                continue;
            }
            if(i>=pos+curlen) r=1;
            else r=pos+curlen-i;
            while(i+r<tmp.size()&&i-r>=0&&(tmp[i+r]==tmp[i-r])) r++;
            slen[i]=r-1;
            pos=i;
            curlen=r-1;
            if(maxr<=r-1&&i-slen[i]==0){
                maxr=r-1;
            }
            if(i+r==tmp.size()) break;
        }
        string s1=s.substr(maxr,ns-maxr);
        reverse(s1.begin(),s1.end());
        return s1+s;
    }
};

方法四 KMP解法

这一种方法是比较巧妙的,r=s;reverse(r.begin(),r.end());t=s+"#"+r,要求s从起始位置开始的最长回文子串,就可以转换成t的最长前缀后缀问题;
比如s=ccab,r=bacc,t=ccab#bacc,那么s中最长的回文串cc也就是t中前缀cc
再比如s=aacecaaa,r=aaacecaa,t=aacecaaa#aaacecaa,则最长回文子串是aacecaa,而t中前缀为aacecaa
这里要特别注意需要加上#,这个很重要,防止s=aaa的时候出现错误。
所以这题其实就演变成KMP算法,求解next数组。具体原理见KMP算法(链接:https://blog.csdn.net/v_july_v/article/details/7041827/)
代码;

class Solution {
public:
    string shortestPalindrome(string s) {
        string r=s;
        reverse(r.begin(),r.end());
        string t=s+"#"+r;
        int n=t.size();
        vector<int> idx(n,-1);
        for(int i=1;i<n;i++){
            int p=idx[i-1];
            while(p!=-1&&t[i]!=t[p+1])
                p=idx[p];
            if(p==-1) idx[i]=t[i]==t[0]?0:-1;
            else idx[i]=p+1;
        }
        string tmp=s.substr(idx[n-1]+1,s.size()-idx[n-1]-1);
        reverse(tmp.begin(),tmp.end());
        return tmp+s;
    }
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[C++] LeetCode 214. 最短回文串 的相关文章

随机推荐

  • 谷歌携Blink来势汹汹 WebKit将成明日黄花?

    原文地址 http www csdn net article 2013 04 09 2814815 Google近日宣布将为Chrome浏览器开发新的自主渲染引擎Blink 与WebKit分道扬镳 随后Opera宣称将追随Google 放弃
  • 主流数据库之间对SQL:2003标准的不同实现方法比较(第四部分 查询结果集中间n行数据)

    本文严禁在未征得本人同意的情况下以任何形式进行转载 本人只接受在邮件中的转载申请 如需转载 请发送邮件至 betteryou 126 com 带有偏移量的限制 目标 仅需要结果集中的n行数据 并试图忽略前面m行的数据 通常只在有ORDER
  • 程序员看世界杯

    目录 1 世界杯赛事规则 1 1 赛制 1 2 小组赛 1 3 淘汰赛阶段 1 4 1 8决赛 1 5 半决赛 1 6 决赛 2 大力神杯材质 3 看球心德 4 2022大力神杯赢家 1 世界杯赛事规则 1 1 赛制 世界杯一共进行64场
  • pytorch基本使用_01

    import torch import numpy as np string 在torch中对string不支持 1 可以通过向量one hot来进行分类 2 embedding word2vec glove type check a to
  • 利用nodemcu和mqtt协议让嵌入式设备接入互联网(二.nodejs的安装和配置)

    文章目录 前言 nodejs nvm和nodejs的安装 npm的相关配置 配置npm的global和cache路径 配置npm仓库为国内淘宝镜像 npm下载相关依赖包 npm初始化项目 安装相关依赖包 前言 第一篇讲了怎么用layui做H
  • 在Sonar中配置license和copyright的检查

    现在开源代码越来越多 代码头部的license和copyright信息在开发中容易被遗忘 那么就有必要做一些相关的检查 例如在持续集成CI中加入这方面的检查 当然 目前有很多集成在IDE中的工具来自动添加license和copyright信
  • 区间查询(树状数组之差点问线问题)

    1110 区间查询 时间限制 2 Sec 内存限制 32 MB 提交 162 解决 62 提交 状态 题目描述 食堂有N个打饭窗口 现在正到了午饭时间 每个窗口都排了很多的学生 而且每个窗口排队的人数在不断的变化 现在问你第i个窗口到第j个
  • selenium自动化测试入门 浏览器多窗口切换

    有时web应用会打开多个浏览器窗口 当我们要定位新窗口中的元素时 我们需要将webDriver的handle 句柄 指定到新窗口 什么意思 假设我们打开web应用 在系统运行过程中重新打开一个新窗口 可以是页签 当前浏览器存在两个窗口 这时
  • 宋浩概率论笔记(四)数字特征

    本帖更新数字特征 包含期望 方差 相关系数等 要点在于记忆性质中的各种公式 遇到题目时能迅速利用已知条件计算答案
  • (超详细)单臂路由及操作步骤

    目录 一 前提引入 二 单臂路由概述 2 1概念 2 2单臂路由优点 2 3单臂路由子接口 三 链路类型 四 单臂路由的配置实例 4 1拓扑图 4 2交换机的配置 4 3路由器的配置 4 4主机的配置 4 5连通性测试 五 总结 一 前提引
  • ajax+异步promise+async+await

    ajax是什么 为什么要学 ajax 异步js xml ajax实现客户端和服务端进行异步通信 实现页面的局部更新 好处 局部刷新 用户体验好 异步通信 加快了响应能力 减少冗余请求 减轻了服务器负担 ajax原理就是 通过xml对象向服务
  • 用python绘制一条直线_python绘制直线的方法

    本文实例为大家分享了python绘制直线的具体代码 供大家参考 具体内容如下 usr bin env python import vtk 绘制通用方法 def myshow linepolydata Now we ll look at it
  • 1km分辨率全球夜间灯光数据(2012-2022)

    数据简介 夜间灯光 一方面直接反映着当地的工业化水平和城市化水平 另一方面 也能部分反映着人口集中分布情况 同时 根据地表夜间灯光亮度 从而在一定程度上表征人类活动强度 长时间序列的夜间灯光数据被广泛运用于多个领域 一些学者将这一指标当作真
  • el-cascader级联选择器单选/多选根据接口懒加载动态获取数据

    在Vue项目中 使用elment ui 中 el cascader 级联选择器 级联选择器每一级的内容对应不同的接口 因此我们要采用懒加载的形式实现对数据的动态获取 主要思路 通过 lazy 开启动态懒加载 并使用 lazyLoad 来设置
  • Spri-n-g-Cl-oud-发-布

    https www cnblogs com lexiaofei tag SpringCloud
  • 数据库number 对应java_数据库中的number型表示什么

    本文收集整理关于数据库中的number型表示什么的相关议题 使用内容导航快速到达 内容导航 Q1 数据库中的number类型在java类中应该是什么类型 数据库中的number类型在java类对应的类型 1 如果number类没有设置小数位
  • GSM模块_STM32实现GPRS与服务器数据传输经验总结

    硬件环境 MCU STM32F103RET6 调试器 J Link GSM模块 Ai Thinker A6 安信可 还需要配一个串口打印工具 当初选这个模块纯粹是因为价格是最便宜的 软件环境 Keil4 开篇废话 经过两周时间的编码 调试
  • 字符串全排列 java实现

    项目github地址 bitcarmanlee easy algorithm interview and practice 欢迎大家star 留言 一起学习进步 经常会遇到字符串全排列的问题 例如 输入为 a b c 则其全排列组合为abc
  • C++ vector、array和数组的比较

    在c 11中 STL中提拱了一个新的容器std array 该容器在某些程度上替代了之前版本的std vector的使用 更可以替代之前的自建数组的使用 那针对这三种不同的使用方式 先简单的做个比较 相同点 三者均可以使用下表运算符对元素进
  • [C++] LeetCode 214. 最短回文串

    题目 给定一个字符串 s 你可以通过在字符串前面添加字符将其转换为回文串 找到并返回可以用这种方式转换的最短回文串 示例 1 输入 aacecaaa 输出 aaacecaaa 示例 2 输入 abcd 输出 dcbabcd 思路解析 这题考