给定一个字符串str,想通过添加字符的方式使得str整体都变成回文字符串,但要求只能在str的末尾添加字符,请返回在str后面添加的最短字符串
[举例]
str = "abcd123321",在必须包含最后一个字符的情况下,最长的回文子串是"123321",之前不是最长回文子串的部分是'abcd",所以末尾应该添加的部分就是"dcba"。
[要求] 如果str的长度为N,解决进阶问题的时间复杂度为O(N).
保证输入数据无回文串
输入为一个字符串str
输出一个字符串。
abcd123321
dcba
添加后的字符串为abcd123321dcba
ababab
a
设N表示输入字符串的长度保证输入字符中只含有小写字母及数字
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String s = br.readLine(); char[] str = preprocessing(s.toCharArray()); // 预处理原始字符串,往每个字符之间加# int C = -1; int R = -1; int[] pArr = new int[str.length]; for(int i=0; i<str.length; i++){ pArr[i] = i<R ? Math.min(pArr[2*C-i],R-i) : 1; while(i+pArr[i]<str.length && i-pArr[i]>-1){ if(str[i-pArr[i]]==str[i+pArr[i]]){ pArr[i]++; }else{ break; } } if(i+pArr[i]>R){ R=i+pArr[i]; C = i; } } int index= C-pArr[C]; StringBuilder sb = new StringBuilder(); while(index>=0){ sb.append(str[index]=='#' ? "" : str[index]); index--; } System.out.println(sb.toString()); } private static char[] preprocessing(char[] str) { StringBuilder sb = new StringBuilder(); for(char c: str) sb.append("#").append(c); sb.append("#"); return sb.toString().toCharArray(); } }
#include <iostream> #include <string> #include <algorithm> #include <limits.h> #include <vector> using namespace std; string fillStr(string s){ string str(s.size() * 2 + 1, '#'); for(int i = 0; i < s.size(); i++){ str[2 * i + 1] = s[i]; } return str; } int manacher(string s){ string str = fillStr(s); int R = -1; int C = -1; vector<int> pArr(str.size(), 0); int maxVal = INT_MIN; for(int i = 0; i < str.size(); i++){ pArr[i] = i < R ? min(pArr[2 * C - i], R - i) : -1; while(i + pArr[i] < str.size() && i - pArr[i] > -1){ if(str[i + pArr[i]] == str[i - pArr[i]]){ pArr[i]++; } else break; } if(i + pArr[i] > R){ R = i + pArr[i]; C = i; } if(R == str.size()){ maxVal = max(maxVal, pArr[i]); } } return maxVal < 0 ? 0 : maxVal - 1; } int main(void){ string s; cin >> s; int maxVal = manacher(s); string ans = s.substr(0, s.size() - maxVal); reverse(ans.begin(), ans.end()); cout << ans << endl; return 0; }这道题解法在于知道马拉车算法怎么求
int main() { string str; cin>>str; string s; s+='#'; for(int i=0;i<str.size();i++) { s+=str[i]; s+='#'; } //预处理 int len=s.size();//预处理后的长度 vector<int> dp(len,0);//dp[i]表示i位置的可以向外回文延长的长度、 int center=0; int max_right=0; for(int i=1;i<len;i++) { //计算dp[i] if(i<max_right) dp[i]=min(dp[2*center-i],max_right-i); else dp[i]=1; while(i-dp[i]>0 && i+dp[i]<len && s[i-dp[i]]==s[i+dp[i]]) dp[i]++; if(i+dp[i]>max_right) { max_right=i+dp[i]; center=i; } } for(int i=2*center-len;i>=0;i--) if(i%2==1) //过滤掉'#' cout<<s[i]; }
#include<cstdio> (802)#include<cstring> bool ishuiwen(char str[],int l,int r){ int k=0; for(int i=l;i<=(l+r)/2;++i){ if(str[i]!=str[r-k]) return false; ++k; } return true; } int main(){ char str[500010]; while(scanf("%s",str)!=EOF){ int len=strlen(str); int i; for(i=0;i<len;++i){ if(ishuiwen(str,i,len-1)) break; } for(i=i-1;i>=0;--i){ printf("%c",str[i]); } } return 0; }