1.暴力法
string longestPalindrome(string s) {
if (s == "") {
return "";
}
int len = s.length();
for (int i = len; i > 0; i--) {
for (int begin = 0; begin + i-1 < len; begin++) {
string ss = s.substr(begin, i);
if (isPal(ss)) {
return ss;
}
}
}
return "";
}
bool isPal(string s) {
if (s == "") {
return true;
}
string s1 = s;
reverse(s1.begin(),s1.end());
if (s == s1) {
return true;
}
return false;
}
2.倒置字符串,求出原字符串和倒置字符串的最长公共子串,注意下标对应问题(判断最后一个位置即可),下标不对应代表不是回文
string longestPalindrome(string s) {
if (s == "") {
return "";
}
string s1 = s;
reverse(s1.begin(), s1.end());
int m = s.length() + 1;
int** arr = new int*[m];
for (int i = 0; i < m; i++) {
arr[i] = new int[m];
}
for (int i = 0; i < m; i++) {
arr[0][i] = 0;
arr[i][0] = 0;
}
//储存最大位置
int max = 0, max_i = 0;
for (int i = 1; i < m; i++) {
for (int j = 1; j < m; j++) {
if (s[i - 1] == s1[j - 1]) {
arr[i][j] = arr[i - 1][j - 1] + 1;
//更新最大值位置
if (arr[i][j] > max) {
//判断下标是否对应
if ((m - 2) - (j - 1) + arr[i][j] - 1 == i - 1) {
max = arr[i][j];
max_i = i - 1;
}
}
}
else {
arr[i][j] = 0;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
cout << arr[i][j];
}
cout << endl;
}
//取出公共字符串
string maxPal = s.substr(max_i - max + 1, max);
return maxPal;
}
3.动态规划法(暴力算法的优化)
按长度递增依次遍历所有长度,长度为一二时单独考虑,为其它时从一二递推即可,首尾相同且去掉首尾为回文,则本身为回文
string longestPalindrome(string s) {
if (s == "") {
return "";
}
int len = s.length();
string maxPal = "";
//P中存下标之间是否是回文
int** P = new int*[len];
for (int i = 0; i < len; i++) {
P[i] = new int[len];
}
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
P[i][j] = 0;
}
}
//计算最长回文子串
int _start = 0, _len = 0;
for (int i = 1; i <= len; i++) {
for (int begin = 0; begin + i <= len; begin++) {
int end = begin + i - 1;
//递推式(长度依次递增,但保存了短的情况,长的只需递推即可,不需要重复计算)
if ((i == 1 || i == 2 || P[begin + 1][end - 1]) && s[begin] == s[end]) {
P[begin][end] = 1;
_start = begin;
_len = i;
}
}
}
maxPal = s.substr(_start, _len);
return maxPal;
}
4.中心拓展法
中心有单中心和双中心,所以共有2n-1个中心,向两边拓展
string longestPalindrome(string s) {
if (s == "") {
return "";
}
int len = s.length();
if (len == 1) {
return s;
}
string maxPal = "";
int maxLen = 0, start = 0;
for (int i = 0; i < len - 1; i++) {
int len1 = longestAroundCenter(s, i, i);
if (len1 > maxLen) {
maxLen = len1;
start = i - len1 / 2;
}
int len2 = longestAroundCenter(s, i, i + 1);
if (len2 > maxLen) {
maxLen = len2;
start = i - len2 / 2 + 1;
}
}
maxPal = s.substr(start, maxLen);
return maxPal;
}
int longestAroundCenter(string s, int i, int j) {
int left = i, right = j;
if ((left >= 0) && (right <= s.length() - 1) && (s[left] == s[right])) {
left--;
right++;
}
return right - left + 1 - 2;//最后拓展的不符合需要减去
}