首页 > 试题广场 >

小易爱回文

[编程题]小易爱回文
  • 热度指数:4533 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

小易得到了一个仅包含大小写英文字符的字符串,该字符串可能不是回文串。(“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串,“asds”就不是回文串。)

小易可以在字符串尾部加入任意数量的任意字符,使其字符串变成回文串。

现在请你编写一个程序,程序要能计算出小易可以得到的最短回文串。


输入描述:
一行包括一个字符串


输出描述:
一行包括一个字符串,代表答案。
示例1

输入

noon

输出

noon
示例2

输入

noo

输出

noon
示例3

输入

helloworld

输出

helloworldlrowolleh
基于JavaScript的解题思路,感觉检测回文可以优化一些,有可以优化的地方欢迎指出
line=readline();
function huiwen(Strs){        //检测是否为回文的函数
    var str = Strs;
    var flag= true;
    var a = str.split('');
    var b = a.concat().reverse();
    a.forEach(function(val,ind){
        if(val!=b[ind]){ 
            flag=false; 
            return false; 
        }
    })
    if(flag){
        return str;
    }
    return false;
}
var word = line;                //构造回文
for(let j=0;j<line.length;j++){
    if(huiwen(word)){
        print(huiwen(word));
        break;
    }
var arr=word.split('');
arr.splice(line.length,0,arr[j]);
word = arr.join('');
}


发表于 2021-11-03 23:51:34 回复(0)
#include<bits/stdc++.h>
using namespace std;

int malache(string s){//马拉车算法
    vector<int> R(2*s.size()+1,-1) ;
    int r = -1 ,c = -1;
    int index =0,temp;
    string tmp(2*s.size() +1,'#');
    for(int i=0;i < tmp.size();i++)
    {
        if(i % 2)
            tmp[i] = s[index++];
    }
    for(int i =0;i < tmp.size();i++)
    {
        R[i] = r > i ? min(R[2*c - i],r - i) : 1;
        while(i + R[i] < tmp.size() && i - R[i] > -1)
        {
            if(tmp[i + R[i]] == tmp[i - R[i]])
                R[i]++;
            else
                break;
        }
        if(i + R[i] > r)
        {
            r = i + R[i];
            c = i;
        }
        if(r == tmp.size())
        {
            temp = i;
            break;
        }
    }
    return R[temp]-1;

}

int main(){
    string str;
    cin >> str;
    int end =  str.size()-1;
    int r = malache(str);
    for(int i=end-r;i>=0;i--){
        str+=str[i];
    }
    cout << str << endl;
    return 0;
}


编辑于 2021-03-31 17:49:24 回复(0)
s=input()
revs=s[::-1]  #helol的最后两位  loleh首两位   相等 则拼接它们
for i in range(len(s)):
    if s[i:]==revs[:len(s)-i]:
        print(s+revs[len(s)-i:])
        break
    

发表于 2021-03-10 16:06:02 回复(0)
def ss_ss(ss,reversed_s):
    ss1 = []
    len_reversed_s = len(reversed_s) for i in range(len_reversed_s):
        str1 = reversed_s[i+1: len(reversed_s)+1] if s + str1 == ''.join(reversed(s + str1)):
            ss = s + str1
            ss1.append(ss) print(min(ss1,key = len)) return True if __name__ == '__main__':
    s = input()
    reversed_s = s[::-1] if s == reversed_s: print(s) else:
        ss = s + reversed_s if ss_ss(ss,reversed_s) is not True: print(ss)
发表于 2021-02-28 15:14:47 回复(0)
str = input().strip()
str1 = ''
str2 = ''
n = len(str)
list1, list2 = [], []
for i in str[::-1]:
    str1 += i
if str1 == str:
    print(str)
else:
    for i in range(n):
        list1.append(str[i])
        if str[i+1:] == str1[:(-i-1)]:

            break

    list1.reverse()
    for i in range(len(list1)):
        str += list1[i]
    print(str)
小白一枚 仅仅有个思路代码写的不够专业,请各位大神指点
发表于 2021-02-14 11:53:38 回复(0)
#include<bits/stdc++.h>
using namespace std;

const int MAXL = 3000;
int main()
{
    string s;
    cin>>s;
    int l = s.size();
    for (int i = 0; i < l; i++)
    {
        string temp = s;
        reverse(temp.begin(), temp.end());
        if (s == temp) break;
        s.insert(s.begin()+l, s[i]);
    }
    cout<<s;
    return 0;
}

发表于 2021-01-14 21:36:00 回复(4)
寻找原始字符串中回文部分开始的索引
s = input().strip()
# 左右边界
l, r = 0, len(s) - 1
# mark记录回文部分的开始位置
mark = -1
while l <= r:
    # 从两端开始检查,如果两端的字符相等,则l指针向右移动,r指针向左移动
    if s[l] == s[r]:
        mark = l if mark == -1 else mark
        l += 1
        r -= 1
        continue
    # 否则原始字符串不是回文串
    if mark != -1:
        l = mark + 1
        mark = -1
        r = len(s) - 1
    else:
        l += 1
# 如果mark是0,表示原来的字符串就是回文串(回文串从索引0开始)
if mark >= 0:
    # mark大于0的时候就要将0~mark-1的部分反转后拼接在原始字符串后面
    s += s[:mark][::-1]
else:
    # 如果mark是-1,则表示原始字符串完全没有回文的部分,直接将原始字符串反转拼接在后面
    s += s[:-1][::-1]
print(s)


编辑于 2021-01-22 14:12:14 回复(1)
直接暴力搜索以右边界为结束点的回文子串的最大长度
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
 
bool judge(string& s, int l, int r)
{
    bool ret = true;
    while(l<r)
    {
        if(s[l]!=s[r])
        {
            ret = false;
            break;
        }
        l++;
        r--;
    }
    return ret;
}
 
int main()
{
    string s;
    int n,t;
    cin>>s;
    n=s.size();
    t=n-1;
    for(int i=n-1;i>=0;i--)
    {
        if(judge(s,i,n-1))
        {
            t=i;
        }
    }
    for(int i=t-1;i>=0;i--)
        s+=s[i];
    cout<<s<<endl;
    return 0;
}

发表于 2021-03-04 10:26:33 回复(1)
#include<iostream>
using namespace std;

// 判断s[index:]是否回文
bool isPalindrome(string& s, int index, int size){
    for(int i = index, j = size-1; i <= j; i++, j--){
        if(s[i] != s[j]) return false;
    }
    return true;
}

int main(){
    string s;
    cin >> s;
    int size = s.size();
    for(int i = 0; i < size; i++){
        if(isPalindrome(s, i, size)){
            cout << s;
            break;
        }
        s.insert(s.begin() + size, s[i]);
    }
    return 0;
}

发表于 2021-08-20 20:35:06 回复(1)
str_or=input()
n=len(str_or)
if str_or==str_or[::-1]:
    print(str_or)
else:
    for i in range(1,n):
        if str_or[i:]==str_or[i:][::-1]:
            print(str_or+str_or[:i][::-1])
            break
如果是回文就直接返回,如果不是可以从头往后找,如果发现后方出现回文,那么将前方字符串反转后添加到后方
发表于 2021-08-09 22:57:43 回复(2)
import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        
        StringBuffer sf = new StringBuffer(str);
        StringBuffer tmp = new StringBuffer(str);
        tmp = tmp.reverse();
        //先判断 本身是否是一个回文串
        if(tmp.toString().equals(sf.toString())) {
            System.out.println(str);
            return;
        }
        //遍历字符串 每次在len下标添加str.charAt[i] 建议画图 一画图就会了
        //值得注意的是StringBuffer和SringBuilder都没有equals()方法 要转化为字符串
        //并且要使用tmp来逆置字符串  因为使用sf来逆置字符串 那么sf本身也被逆置了
        int len = str.length();
        for(int i = 0;i < str.length();i++) {
            sf.insert(len,str.charAt(i));
            tmp = new StringBuffer(sf);
            tmp = tmp.reverse();
            if(tmp.toString().equals(sf.toString())) {
                break;
            }
        }
        System.out.println(tmp);
    }
}

发表于 2021-06-03 23:07:15 回复(0)
很简单的暴力解法
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
bool test(string str)
{
    string rev = str;
    reverse(rev.begin(), rev.end());
    return rev == str;
}
int main()
{
    string input;
    cin >> input;
    string rev = input;
    string output = input;
    string s = input;
    reverse(rev.begin(), rev.end());
    int index = 0;
    string add;
    //cout << input.substr(0,1) << endl;
    while (!test(output))
    {
        output = input;
        add = input.substr(0, index);
        reverse(add.begin(), add.end());
        output += add;
        index++;
    }
    cout << output << endl;
    return 0;
}


发表于 2021-03-30 17:33:45 回复(0)
# Python3
s = str(input().strip())
# 左右边界
start = 0
end = len(s)-1
while(start<end):
    if(s[start]==s[end]):
        start += 1
        end -= 1
    else:
        # 记录需要进行重复的字符串
        adds = list(s[:start+1])
        start += 1
        end = len(s)-1
adds.reverse()
print(s+''.join(adds))


发表于 2021-03-22 16:31:32 回复(0)
判断是否是回文数 大家都会, 重点是怎么补全回文数 且 让回文数长度最短
找 '对称轴': 即从输入尾部倒着遍历 找出最大的回文子串, 找到了对称轴, 拿着输入减去对称轴, 剩下的部分就是需要回文的部分, 反转字符串再加到输入后面就可以了
s = input()
if len(s) == 1:
    print(s)
def checkPalindrome(string):
    if len(string) == 1:
        return True
    deque = [i for i in string]
    flag = True
    while len(deque) > 1 and flag:
        if deque.pop(0) == deque.pop():
            pass
        else:
            flag = False
    return flag
 
if checkPalindrome(s):
    print(s)
else:
    symmetry = s[-1]
    temp = ''
    for i in range(len(s) - 1, -1, -1):
        temp += s[i]
        if checkPalindrome(temp):
            if len(temp) > len(symmetry):
                symmetry = temp
 
    if len(symmetry) == 1:
        sym_part = s[:len(s) - 1]
        reversed_sym_part = sym_part[::-1]
        print(s + reversed_sym_part)
    else:
        palinlen = len(s)
        symlen = len(symmetry)
        sym_part = s[:palinlen - symlen]
        reversed_sym_part = sym_part[::-1]
        print(s + reversed_sym_part)



发表于 2021-03-05 23:27:19 回复(0)
写个暴力解 (go语言)
O(n2)
优解LC  214
package main
import "fmt"
func isPalind(s string) bool {
    for i, j := 0, len(s) - 1; i < j; i, j = i + 1, j - 1 {
        if (s[i] != s[j]) {
            return false;
        }
    }
    return true;
}
func reverse(t string) string {
    s := []byte(t)
    for i, j := 0, len(s) - 1; i < j; i, j = i + 1, j - 1 {
        s[i], s[j] = s[j], s[i]
    }
    return string(s)
}
func main() {
    var s string
    fmt.Scanln(&s)
    n := len(s)
    for i := 0; i < n; i++ {
        if (isPalind(s[i:n])) {
            s += reverse(s[:i])
            fmt.Println(s)
            break;
        }
    }
}
// C++字符串哈希(O(n))
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

using ull = unsigned long long;
ull mod = 1e9 + 7;

int main() {
    string s;
    cin >> s;
    int pos = s.size() - 1;
    if (s.empty())    cout << " " << endl;
    ull base = 131, buff = 1;
    ull left = 0, right = 0; 
    for (int i = s.size() - 1; i >= 0; --i) {
        (left = left * base + s[i]) %= mod;
        (right = right + buff * s[i]) %= mod;
        if (left == right)     pos = i;
        (buff *= base) %= mod;
    }
    string str = s.substr(0, pos);
    reverse(str.begin(), str.end());
    s += str;
    cout << s << endl;

    return 0;
}
编辑于 2021-03-12 12:45:47 回复(0)
import java.util.Scanner;
public class Main {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        StringBuffer sb = new StringBuffer();
        sb.append(sc.nextLine());
        int le = sb.length();
        if (le <= 2) {
            System.out.println(le==2?(sb.charAt(0)==sb.charAt(1)?sb:sb+String.valueOf(sb.charAt(0))):sb);
        } else {
            int max = 0;
            int start = 0;
            int end = 0;
            int[][] dp = new int[le][le];
            for (int i = 0; i < le; i++) {
                for (int j = 0; j < i; j++) {
                    if (sb.charAt(j) == sb.charAt(i) && (i - j < 2 || dp[j + 1][i - 1] > 0)) {
                        dp[j][i] = i - j + 1;
                        if (dp[j][i] > max) {
                            start = j;
                            end = i;
                        }
                    }
                }
            }
            if (start == 0 && end == le - 1) {
                System.out.println(sb);
            } else if (end == le - 1) {
                System.out.println(sb + sb.reverse().substring(le - start));
            } else {
                System.out.println(sb + sb.reverse().substring(1));
            }
        }
    }
}

发表于 2021-01-22 21:36:50 回复(0)
  • 逆序 原串,寻找 前缀,简单易懂
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        // 逆序原字符串
        String reverse = new StringBuffer(s).reverse().toString();
        String ans = "";
        int len = Integer.MAX_VALUE;

        if(judge(s)) {
            System.out.println(s);
        } else {
            for(int i=0;i<reverse.length();i++){
                // 寻找r对应s的前缀
                /**
                   i s(YCiC) r(CiCY)的前缀
                   0 YCiC    no
                   1 CiC     yes:CiC
                               CiC后追加(Y)
                               Y的index=r.length()-i
                 */
                if(reverse.startsWith(s.substring(i))){
                    String tmp = s+reverse.substring(reverse.length()-i);
                    if (tmp.length() < len) {
                        len = tmp.length();
                        ans = tmp;
                    }
                    // 为什么不直接输出呢?因为可能会有多个输出,我要输出最短的那个
                    // System.out.println(s+reverse.substring(reverse.length()-i));
                }
            }
             System.out.println(ans);
        }

    }

    public static boolean judge(String s) {
        int left = 0, right = s.length() - 1;
        while(left <= right) {
            if(s.charAt(left) == s.charAt(right)) {
                left++;
                right--;
            } else {
                return false;
            }
        }
        return true;
    }
}
发表于 2021-09-24 23:27:25 回复(0)
using System;
using System.Collections.Generic;
public class Program {
    public static void Main() {
        string str01 = Console.ReadLine();
        string str02 = "";
        for (int i = str01.Length - 1; i >= 0; i--) {
            str02 += str01[i];
        }
        if (str01 == str02) {
            Console.WriteLine(str02);
        } else {
            string str03 = "";
            string str04 = "";

            for (int i = 0; i < str01.Length; i++) {
                str04 = str01;
                str03 += str01[i];
                for (int j = str03.Length - 1; j >= 0; j--) {
                    str04 += str03[j];
                }
                
                if (Justs(str04))
                    break;
            }
            Console.WriteLine(str04);
        }

    }


   static bool Justs(string str) {
        for (int i = 0; i < str.Length; i++) {
            if (str[str.Length - i - 1] != str[i])
                return false;
        }
        return true;
    }
}
编辑于 2023-12-29 01:22:39 回复(0)
#include <iostream>
using namespace std;

string Netease4(string s)
{
    int n = s.length();
    int mid = (n - 1) / 2;
    int minStart = n-2;
    for (int i = mid; i < n; i++)
    {
        char t = s[i];
        int left = i-1;
        int right = i+1;
        while (right<n&&s[right] == t)
        {
            right++;
        }
        while (left>=0&&s[left] == t)
        {
            left--;
        }
        while (left>-1&&right<n&&s[left] == s[right])
        {
            left--;
            right++;
        }
        if (right == n)
        {
            minStart = min(left, minStart);
        }
    }
    for (int i = minStart; i > -1; i--)
        s += s[i];
    return s;
}
int main() {
    string b;
    cin >> b;
     cout << Netease4(b);
   
}
// 64 位输出请用 printf("%lld")

发表于 2023-08-04 10:03:26 回复(0)
死活过不了所有用例(超时了!天不生我 Java,求大佬帮忙,做了好多题目都是写出来了超时),暴力搜索,固定右边界;
// 马拉车算法找最长回文子串(第一时间想到了这个,题解没有用到)
import java.util.Scanner;
import java.lang.StringBuilder;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        char[] chs = sc.nextLine().toCharArray();
        int left = 0, right = chs.length - 1;
        // 找对称轴
        while (left < right) {
            while (left < right && chs[left] != chs[right]) {
                left++;
            }
            if (judge(chs, left, right)) {
                break;
            }
        }
        if (left == 0) { // 说明已经是回文字串了
            System.out.println(String.valueOf(chs));
        } else {
            StringBuilder builder = new StringBuilder();
            builder.append(chs);
            for (int i = left - 1; i >= 0; --i) {
                builder.append(chs[i]);
            }
            System.out.println(builder.toString());
        }
    }
    public static boolean judge(char[] chs, int begin, int end) {
        while (begin < end) {
            if (chs[begin++] != chs[end--]) {
                return false;
            }
        }
        return true;
    }
}


发表于 2022-08-24 06:58:10 回复(0)