givenString =input() def isReverse(s): return s ==''.join(reversed(s)) answer ="" for i in range(len(givenString)+1): for j in range(i): target = givenString[j:i] if isReverse(target) and len(target) > len(answer): answer =target print(answer)
#include<bits/stdc++.h>
using namespace std;
bool isco(string str,int l,int r){ //判断在str中,下标区间[l,r]的字符串是否是回文
string a1="",a2="";
for(int i = l;i <= r;i++) a1 += str[i];
for(int i = r;i >= l;i--) a2 += str[i];
if(a1==a2) return true;
return false;
}
string maxs;
int maxn;
int main(){
string str;
cin >> str;
//枚举答案
for(int l = 0;l < str.size();l++){
for(int r = l;r < str.size();r++){
if(isco(str,l,r)){
if(r-l+1>maxn){
maxn = r-l+1;
maxs = "";
for(int i = l;i <= r;i++) maxs += str[i];
}
}
}
}
cout << maxs;
return 0;
} #include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
string maxHui(string s)
{
int len = s.length();
if(len <= 1)
return s;
string s2 = s;
reverse(s2.begin(), s2.end());
vector<vector<int>> dp(len+1, vector<int>(len+1, 0));
int res = 0, pos = 0;
for(int i = 1; i <= len; i++)
{
for(int j = 1; j < len+1; j++)
{
if(s[i-1] == s2[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
if(res <= dp[i][j])
{
res=dp[i][j];
pos = i-1;
}
}
}
return s.substr(pos-res+1, res);
}
int main()
{
string str;
while(getline(cin, str))
cout << maxHui(str) << endl;
return 0;
} #include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
string mk_str(string s) {
string temp = "$#";
for (size_t i = 0; i < s.size(); i++) {
temp = temp + s[i];
temp = temp + "#";
}
return temp;
}
int main() {
string str;
cin >> str;
str = mk_str(str);
vector<int> len(str.size());
int right = 0, max_len = 0, max_point = 0, pos = 0;
for (size_t k = 1; k < str.size(); k++) {
int i = k;
len[i] = i < right ? min(right - i, len[2 * pos - i]) : 1;
while(str[i + len[i]] == str[i - len[i]]) len[i]++;
if (i + len[i] > right) {
right = i + len[i];
pos = i;
}
if (len[i] > max_len) {
max_len = len[i];
max_point = i;
}
}
for (int i = max_point - max_len + 1; i <= max_point + max_len - 1; i++) str[i] == '#' || cout << str[i];
cout << endl;
return 0;
} #include <bits/stdc++.h>
using namespace std;
int main(){
string s,t="";
cin>>s;
int n=s.length(), Max=0;
for(int i=0;i<n-1;i++){
int l=i,r=i+1;
while(l>=0 && r<=n-1 && s[l--]==s[r++])
if(r-l-1>Max){
Max = r-l-1;
t = s.substr(l+1, r-l-1);
}
}
for(int i=1;i<n-1;i++){
int l=i-1,r=i+1;
while(l>=0 && r<=n-1 && s[l--]==s[r++])
if(r-l-1>Max){
Max = r-l-1;
t = s.substr(l+1, r-l-1);
}
}
if(t=="")
cout<<s[0]<<endl;
else
cout<<t<<endl;
return 0;
} #include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
string str;
cin >> str;
int n = str.size();
pair<int, int> res = { 1, 0 };
vector<vector<bool>> a(n , vector<bool>(n,false));
for (int i = n - 1; i >= 0; i--) a[i][i] = true;
for (int i = n - 1; i >= 0; i--)
for (int j = i + 1; j < n; j++)
{
if (j == i + 1 && str[i] == str[j])
{
a[i][j] = true;
if (j - i + 1 > res.first)
res = { j - i + 1, i };
}
else if (j>i + 1 && str[i] == str[j] && a[i + 1][j - 1])
{
a[i][j] = true;
if (j - i + 1 > res.first)
res = { j - i + 1, i };
}
}
string str_res = str.substr(res.second, res.first);
cout << str_res << endl;
return 0;
} /*
求最长对称子串
考虑动态规划,设dp[x][y]为从x到y的子串是否对称,若对称表示长度,不对称为-1
子串长度从1到n遍历
当 dp[x+1][y-1] != -1 并且 s[x] == s[y] ,则 dp[x][y] = dp[x+1][y-1] + 2 ;
否则 dp[x][y] = -1
边界条件 x==y dp[x][y] = 1 ; x<y dp[x][y] = 0
*/
#include<bits/stdc++.h>
using namespace std;
#define N 10000
int main()
{
// freopen("input.txt", "r", stdin);
char s[N];
cin >> s;
int n = strlen(s);
int dp[n][n];
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i++) {
for(int j = 0; j + i < n; j++) {
if(i == 0) dp[j][j] = 1;
else {
if(dp[j + 1][j + i - 1] == -1 || s[j] != s[j + i]) dp[j][j + i] = -1;
else dp[j][j + i] = dp[j + 1][j + i - 1] + 2;
}
}
}
int ans = 0, x, y;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(dp[i][j] > ans) {
ans = dp[i][j];
x = i;
y = j;
}
for(int i = x; i <= y; i++) {
cout << s[i];
}
cout << endl;
return 0;
}
因为给定一个字符串,只含数字或大小写字母,可以在每相邻字符之间添加'*',就不用分aba和abba两种情况了。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
// 在每相邻两个字符之间添加‘*’
str = str.replaceAll(".", "*$0").substring(1);
int maxArea = 0, maxIndex = 0;
for (int i = 0; i < str.length(); i++) {
int temp = getArea(str, i);
if (temp > maxArea) {
maxArea = temp;
maxIndex = i;
}
}
System.out.println(str.substring(maxIndex - maxArea, maxIndex + maxArea + 1).replace("*", ""));
}
private static int getArea(String str, int index) {
int area = 0;
int left = index - 1, right = index + 1;
while (left >= 0 && right <= str.length() - 1) {
// 向左右两边扩展
if (str.charAt(left--) == str.charAt(right++)) {
area++;
} else {
break;
}
}
return area;
}
}
有些人没仔细看,晚、安的方法并没有问题。但是它的方法遍历了所有的子字符串,这个工作量是最大的,字符越多压力增加得越快,代码还可以优化,其实可以及时的break出来的。
我的思路是,回文无非两种可能,偶数类对称和奇数类对称,那我从最小的回文开始往外扩大,就没有漏洞了。
排除极端情况单个字母,余下的情况就是一个for循环从左往右遍历,回文的起点不是aa就是aba,所以我先找起点,之后往外圈一次次判断就完了,一旦不符合条件跳出循环对比长度选择保存,然后下一个循环即可,所以就是一个for套一个while。代码是边提交边修补写的,很烂,主要是为了过关答题。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(){
string str,tmp,max,rev;
while(cin >> str){
max=str[0];
for(int i=0;i<str.length();i++){
for(int j=str.length();j>i;j--){
if(str[i]==str[j]){
rev=str.substr(i,j+1-i);
tmp= rev;
reverse(rev.begin(),rev.end());
if(tmp == rev)
if(tmp.length()>max.length()){
max=tmp;
break;
}
}
}
}
cout << max;
}
return 0;
}
JavaScript,当时并没有成功,当时忘记reverse()把原数组也会反转,现在测试是可以的,有改进和错误请告诉我,万分感谢
function findLonglestSubStr(str){
// 将字符串转换为数组
let arr=str.split('');
let result=[];
// 对长度为0和1的字符串直接返回
if(arr.length<2) return arr.join('');
for(let i=0;i<arr.length;i++){
// 从arr截取下标i到结尾的数组给arr2
let arr2=arr.slice(i);
// 找到以该字母为起始点的最长回文串
while(arr2.join('')!==[...arr2].reverse().join('')){
arr2.pop();
}
/*
如果最终这个数组剩下超过1的长度,而且比最终要返回的结果数组长度要大,则返回结果数组指向这个回文数组
*/
if(arr2.length!==1 && arr2.length>result.length) result=arr2;
}
return result.join('');
}
console.log(findLonglestSubStr('abbaad')); // abbaa
console.log(findLonglestSubStr('a')); // a
console.log(findLonglestSubStr('abccbd')); //bccb
var line=readline(); //读取输入字符串
var len=line.length;
function reverseStr(str){ //反转字符串
return str.split("").reverse().join("");
}
function getSymmetry(str){
var maxSubString="";
for(var i=0;i<len;i++){ //两for循环获得子字符串
for(var j=len;j>i;j--){ //并判断获取的子字符串是否是对称字符串
var temp=str.substring(i,j);
if(temp===reverseStr(temp) && maxSubString.length<temp.length){
maxSubString=temp;
}
}
}
return maxSubString;
}
if(len==1){
console.log(line)
}else{
console.log(getSymmetry(line));
}
#include<bits/stdc++.h>
using namespace std;
bool isTrue(string str){
int len=str.size();
for(int i=0;i<=len/2;i++){
if(str[i]!=str[len-i-1]){
return false;
}
}
return true;
}
int main(){
string str;
cin>>str;
int len=str.size();
if(len==1){
cout<<str<<endl;
}else if(len==2){
if(str[0]==str[1]){
cout<<str<<endl;
}else{
cout<<str[0]<<endl;
}
}else{
string maxString="";
int first=0,end=len;
for(int i=0;i<len;i++){
for(int j=len;j>i;j--){
string temp=str.substr(i,j);
if(isTrue(temp)){
if(temp.size()>maxString.size()){
maxString=temp;
}
}
}
}
cout<<maxString<<endl;
}
return 0;
}
这个题是LeetCode的第5题 最长回文子串,算是第二次遇到,但是我写的还是比人家的答案长得多,乱得多。
思路是:先确定中心再向两边延伸,回文串有两种:
①中心的两个字符是一样的,如"abccba";
②中心只有一个字符,如"abcba"。
所以针对两种情况要分别来求:
①针对第一种,每个字符都可以是中心;
②针对第二种,必须先找到"cc",即通过s[i] == s[i - 1]这样的判断找到两个c中的某一个,然后向两边延伸着找。
下面是LeetCode一个写的比较简洁的答案:
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String input = in.nextLine();
System.out.println(solve(input));
}
public String solve(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
return right - left - 1;
}
}
//动态规划,转移方程:
//dp[i][j]=dp[i+1][j-1]&&str[i]==str[j] (i+1<=j-1)
//dp[i][j]=str[i]==str[j]
#include <bits/stdc++.h>
using namespace std;
int main(){
string str;
int x=0,y=0;
cin>>str;
vector<vector<bool>> dp(str.size(),vector<bool>(str.size(),false));
for(int i=0;i<str.size();i++)
dp[i][i]=true;
for(int k=1;k<str.size();k++){
int j=k,i=0;
while(j<str.size()&&i<str.size()){
if(i+1<=j-1)
dp[i][j]=dp[i+1][j-1]&&str[i]==str[j];
else
dp[i][j]=str[i]==str[j];
if(dp[i][j]==true){
x=i;
y=j;
}
i++;
j++;
}
}
cout<<str.substr(x,y-x+1);
return 0;
}
所有的答案里面居然没有用O(n)复杂度的manacher算法。。。都是O(n^2)的暴力解法。。下面我提供一个AC了的manacher方法,供大家参考,如果是笔试O(n^2)的复杂度能AC那也ok,如果是面试,让你提供一个O(n)复杂度的找最长回文子串的算法,希望能想到是用manacher算法
import java.util.Scanner;
import static java.lang.System.in;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
String str = sc.nextLine();
System.out.println(manacherProcess(str));
}
public static char[] manacherStr(String str) {
char[] arr = str.toCharArray();
char[] manArr = new char[arr.length * 2 + 1];
for (int i = 0, j = 0; i < manArr.length; i++) {
manArr[i] = (i & 1) == 0 ? '#' : arr[j++];
}
return manArr;
}
public static String manacherProcess(String str) {
char[] manArr = manacherStr(str);
int[] pArr = new int[manArr.length];
int index = -1;
int pR = -1;
int maxVal = Integer.MIN_VALUE;
int maxIndex = -1;
for (int i = 0; i < pArr.length; i++) {
pArr[i] = pR > i ? Math.min(pArr[2 * index - i], pR - i) : 1;
while (i + pArr[i] < manArr.length && i - pArr[i] > -1) {
if (manArr[i + pArr[i]] == manArr[i - pArr[i]]) {
pArr[i]++;
} else {
break;
}
}
if (i + pArr[i] > pR) {
pR = i + pArr[i];
index = i;
}
if (pArr[i] > maxVal) {
maxVal = pArr[i];
maxIndex = i;
}
}
String ret = "";
for (int i = maxIndex - maxVal + 1; i < maxIndex + maxVal; i++) {
ret += (i & 1) == 0 ? "" : manArr[i];
}
return ret;
}
}
s = input() if len(s) == 1: print(s) else: max_len = 1 k = 0 for i in range(len(s)): l, r = i, i while l >= 0 and r < len(s) and s[l] == s[r]: current_len = r - l + 1 if current_len > max_len: max_len = current_len k = l l -= 1 r += 1 l, r = i, i + 1 while l >= 0 and r < len(s) and s[l] == s[r]: current_len = r - l + 1 if current_len > max_len: max_len = current_len k = l l -= 1 r += 1 print(s[k:k + max_len])