回文,亦称回环,是正读反读都能一样的字符串。例如“12321”、“abba”等。
现在给你一个字符串,请你找出其中长度最长的回文。
输入有多组数据。
每组数据有一行,包含一个长度小于100个字符的字符串s,且仅由字母和数字构成。
如果有多个长度相等的回文,仅输出第一个。
对应每一组输入,输出其中长度最长的回文字符串。
abcabccbadda abcabccbaddabcc
abccba ccbaddabcc
import sys
def longestPalindrome(s):
if s == s[::-1]: return s
start, maxLen = 0, 1
for i in range(len(s)):
if i - maxLen >= 1 and s[i - maxLen -1:i + 1] == s[i - maxLen - 1:i + 1][::-1]:
start = i - maxLen - 1
maxLen += 2
continue
if i - maxLen >= 0 and s[i - maxLen:i + 1] == s[i - maxLen:i + 1][::-1]:
start = i - maxLen
maxLen += 1
return s[start:start + maxLen]
for i in sys.stdin.readlines():
print (longestPalindrome(i.strip()))
#include<iostream> #include<vector> #include<string> #include<algorithm> #include<functional> #include <map> #include <set> #include <unordered_set> #include <unordered_map> #include <exception> #include <iomanip> #include <memory> #include <sstream> #define INF 1000000 using namespace std; int main(int argc, char** argv) { //freopen("in.txt", "r", stdin); string s; while (cin >> s) { if (s.size() <= 1) { cout << s << endl; continue; } int maxStart = 0, maxLen = 1; for (int i = 0; i < s.size();) { int j = i, k = i; while (k < s.size() - 1 && s[k + 1] == s[k]) ++k; i = k + 1; while (k < s.size() - 1 && j > 0 && s[k + 1] == s[j - 1]) { ++k, --j;} int curLen = k - j + 1; if (curLen > maxLen) { maxStart = j; maxLen = curLen; } } cout << s.substr(maxStart, maxLen) << endl; } return 0; }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String s = sc.next(); String str = "#"; String res = ""; for (int i = 0; i < s.length(); i ++ ) str += s.charAt(i) + "#"; for (int i = 0; i < str.length(); i ++ ) res = res.length() >= check(str, i, i).length() ? res : check(str, i, i); System.out.println(res); } } public static String check(String str, int left, int right) { while (left >= 0 && right < str.length() && str.charAt(left) == str.charAt(right)) { left -- ; right ++ ; } return str.substring(left + 1, right).replace("#", ""); } }
坑点:这题出在栈下, 我不知道怎么解,明明可以有不用栈更简单的方法做出来, 害的我一直在寻思如何用栈解决。我觉得专项练习,对于数据结构算法这样的练习, 出的题应该是在使用数据结构和算法时会比其他方法更简单,更易于理解。 这样练习才知道数据结构和算法的妙处,不然就变成了为了练习而练习了,这样又有什么意思呢。 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <functional> #include <algorithm> #include <numeric> #include <stack> #include <queue> #include <vector> #include <string> #include <sstream> using namespace std; int length (char str[]); bool isReverse (char sub[]); void substr (char str[], char sub[], int i, int num); int length (char str[]) { int len = 0; while (str[len++]); return len - 1; } bool isReverse (char sub[]) { for (int right = 0, left = length (sub) - 1; right < left; right++, left--) { if (sub[right] != sub[left]) { return false; } } return true; } void substr (char str[], char sub[], int i, int num) { int index = 0; for (int x = i; x < num + i; x++) { sub[index++] = str[x]; } } int main () { char str[100] = { 0 }; while ((scanf ("%s", str)) != EOF) { int flag = 1; for (int len = length (str); len > 0 && flag; len--) { for (int i = 0, num = len; i + len - 1 < length (str) && flag; i++) { char sub[100] = { 0 }; substr (str, sub, i, num); if (isReverse (sub)) { cout << sub << endl; flag = 0; } } } } return 0; }
Manacher算法,时间复杂度为O(N)
// write your code here cpp #include <iostream> #include <vector> #include <string> using namespace std; pair<int,int> autoappend(int left,int right, string& num){ while(left >= 0 && right < num.size() && num[left] == num[right]){ left--; right++; } return {left + 1, right - 1}; } int main(){ vector<string> vc; string s; while(cin>>s){ vc.push_back(s); } for(int i = 0; i < vc.size(); i++){ int end = 0; int start = 0; for(int j = 0; j < vc[i].size(); j++){ auto [left1, right1] = autoappend(j, j, vc[i]); auto [left2,right2] = autoappend(j, j + 1, vc[i]); if(right1 - left1 > end - start){ end = right1; start = left1; } if(right2 - left2 > end - start){ end = right2; start = left2; } } cout << vc[i].substr(start,end - start + 1) << endl; } return 0; }
运用Mannacher算法改编,添加一数组来存储每一元素的回文长度和最大回文有边界 ;最后找出整体的最大回文长度
def Mannacher(line):
lenth_line = len(line)
data = ["$","#"]
for i in range(lenth_line):
data.append(line[i])
data.append("#")
R = 1
C = 0
res = []
n = 2*lenth_line+2
rule = [1 for i in range(n)]
# mannacher 算法改变,添加一res数组,存储回文长度和右边界
for i in range(n):
if i<R:
rule[i] = min(R-i,rule[2*C-i])
else:
rule[i] = 1
while(i-rule[i]>=0 and i+rule[i]<n and data[i-rule[i]]==data[i+rule[i]]):
rule[i] += 1
if i+rule[i] > R:
C = i
R = i+rule[i]
res.append([rule[i],C,R])
for i in range(n):
if data[i] =="#":
continue
# 找到最大回文长度 max_r-1
rule.sort()
max_r = rule[-1]
for node in res[1:]:
if node[0] == max_r:
R = int(node[2]/2-1)
break
print(line[R-max_r+1:R])
if __name__ == '__main__':
while(True):
try:
line = input().strip()
Mannacher(line)
except:
break
#思路:动态规划 # 1、dp[i][j] = 1表示字符串s从i到j是回文串 dp[i][j] = 0表示字符串s从i到j不是回文串 # 2、如果dp[i][j] = 1, 那么dp[i+1][j-1] = 1
import sys
def manacher(s):
maxlen = 0
start = 0
dp = [[0 for i in range(len(s))] for i in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
if i+1<len(s) and s[i] == s[i+1]:
dp[i][i+1] = 1
maxlen = 2
start = i
for i in range(3,len(s)+1):
for j in range(len(s)-i+1):
k = i+j-1
if dp[j+1][k-1]==1 and s[j]==s[k]:
dp[j][k] = 1
if i>maxlen:
start = j
maxlen = i
if maxlen>=2:
return s[start:start+maxlen]
return 1
for i in sys.stdin.readlines():
print (manacher(i.strip()))
#include<iostream> #include<string> using namespace std; int main() { string s; while (cin >> s) { if (s.length() == 1) { cout << s << endl; continue; } else if (s.length() == 2) { if (s[0] == s[1]) cout << s << endl; else cout << s[0] << endl; continue; } string res; int maxlength = 0, k; for (int i = 1; i < s.length() - 1; i++) { k = 1; while (i - k >= 0 && i + k < s.length() && s[i - k] == s[i + k]) k++; if (k != 1) { if (maxlength < 2 * k - 1) { maxlength = 2 * k - 1; res.clear(); for (int j = i - k + 1; j < i + k; j++) res += s[j]; } } } for (int i = 1; i < s.length() - 1; i++) { k = 0; while (i - k >= 0 && i + k + 1 < s.length() && s[i - k] == s[i + k + 1]) k++; if (k != 0) { if (maxlength < 2 * k) { maxlength = 2 * k; res.clear(); for (int j = i - k + 1; j < i + k + 1; j++) res += s[j]; } } } if (res.length() == 0) cout << s[0] << endl; else cout << res << endl; } return 0; }
import java.util.Scanner; public class Main{ public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner in = new Scanner(System.in); while(in.hasNext()){ String str = in.next(); int length = str.length(); String a[] = new String[length]; for(int i = 0; i<length; i++){ a[i] = ""; } String b[] = new String[length]; for(int i = 0; i<length; i++){ b[i] = ""; } for(int i = 0; i<length; i++){ for(int j = 0; i-j>=0&&i+j<length; j++){ if(str.charAt(i-j) != str.charAt(i+j)){ break; } a[i] += str.charAt(i-j); } for(int j = 0; i-j>=0&&i+j+1<length; j++){ if(str.charAt(i-j) != str.charAt(i+j+1)){ break; } b[i] += str.charAt(i-j); } } // for(int i = 0; i<length; i++){ // System.out.print(a[i]+" "); // } int max1 = 0; int count1 = 0; for(int i = 0; i<length; i++){ if(a[i].length()>max1){ max1 = a[i].length(); count1 = i; } } StringBuffer sb1 = new StringBuffer(); sb1.append(a[count1].substring(1)); sb1.reverse(); String m = sb1.toString()+a[count1]; // System.out.print(m); // for(int i = 0; i<length; i++){ // System.out.print(b[i]+" "); // } int max2 = 0; int count2 = 0; for(int i = 0; i<length; i++){ if(b[i].length()>max2){ max2 = b[i].length(); count2 = i; } } //System.out.print(count); StringBuffer sb2 = new StringBuffer(); sb2.append(b[count2]); sb2.reverse(); String n = sb2.toString()+b[count2]; // System.out.print(n); System.out.print(m.length()>n.length()?m:n); } in.close(); } }
#include<iostream> #include<string> using namespace std; int main() { int n,len,i,exit,sa; string str,lstr,rstr; while(cin>>str) { exit=0; len=str.length(); for(n=len;n>1;n--) { for(i=0;i<=len-n;i++) { lstr=str.substr(i,n); string rstr(lstr.rbegin(),lstr.rend()); sa=lstr.compare(rstr); if(sa==0) { exit=1; cout<<lstr<<endl; break; } } if(exit==1)break; } if(exit==1)continue; cout<<str[0]<<endl; } return 0; }