动态规划:

class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        if(n <= 1) return n;
        int longest = 1;
        bool dp[n][n];
        for(int i = 0; i < n; i++) { //从短到长对每种长度分别判断,可以这么做是因为判断较长的需要利用较短的
            for(int j = 0; j< n - i; j++) { //从头开始对长度i+1的子字符串判断
                if(i == 0) dp[j][j] = 1; //长度1一定为回文
                else if(i == 1) dp[j][j + 1] = (A[j] == A[j + 1]); //长度2判断头尾是否相等
                else if(A[j] == A[j + i]) dp[j][j + i] = dp[j + 1][j + i - 1]; //长度大于等于3,判断两头是否相等,若相等则同去两头的bool值一样
                else dp[j][j + i] = 0; //否则为0
                if(dp[j][j + i]) longest = max(longest, i + 1); //更新最大值
            }
        }
        return longest;
    }
};

中心扩散法:

class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        if(n <= 1) return n;
        int left = 0, right = 0, longest = 1;
        for(int i = 0; i < n; i++) { //以每个字符为中心左右扩散
            left = right = i; //长度为奇数时
            while(left >= 0 && right < n) { //确保不越界
                if(A[left] == A[right]) { //判断左右字符是否相等
                    longest = max(longest, right - left + 1); //相等时更新最大长度
                    left--;right++; //左右各扩散一位
                }
                else break; //若不相等则退出循环
            }
            left = i;
            right = i + 1; //长度为偶数时
            while(left >= 0 && right < n) { //原理同上
                if(A[left] == A[right]) {
                    longest = max(longest, right - left + 1);
                    left--;right++;
                }
                else break;
            }
        }
        return longest; //返回最大值
    }
};

马拉车算法:(参考马拉车算法 — 百度百科

class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        if(n <= 1) return n;
        A.insert(A.begin(), '#'); //头插入#
        for(int i = 1; i <= n; i++) //每个字符后插入#
            A.insert(A.begin() + 2 * i, '#');
        n = 2 * n + 1; //更新字符串长度
        int longest = 1; //保存最终结果
        int arm_length[n]; //记录每个字符为中心的回文臂长
        for(int i = 0; i < n; i++)
            arm_length[i] = 1; //初始化臂长为1
        int pos = -1, max_dis = -1; //记录覆盖距离最右的字符中心位置和最右端下标
        int left, right; //双指针用于判断两个字符是否相同
        for(int i = 0; i < n; i++) { //从左到右求每个字符的臂长(包括#)
            if(max_dis > i) { //如果最右点在当前点右侧即覆盖了当前点
                if(arm_length[2 * pos - i] + i - 1 <= max_dis) //当前点关于中心点的对称点(以下简称对称点)的臂长加上当前点坐标减1(想象成当前点左右延伸对称点臂长减1),若不超过最右点
                    arm_length[i] = arm_length[2 * pos - i]; //根据对称性质可知当前点与对称点的对称性质相同即臂长相同
                else //若是超过最右点
                    arm_length[i] = max_dis - i + 1; //则当前点最多延伸到最右点,需要后续判断
            }
            left = i - arm_length[i], right = i + arm_length[i]; //当前点加减臂长作为判断字符是否相同的两个位置
            while(left >= 0 && right < n) { //不断向两边延伸判断
                if(A[left--] == A[right++])
                    arm_length[i] ++;
                else break;
            }
            longest = max(longest, arm_length[i] - 1); //更新最长回文长度,注意臂长减1就是回文字符串实际长度
            if(arm_length[i] + i - 1 > max_dis) { //更新最右点
                max_dis = arm_length[i] + i - 1;
                pos = i;
            }
        }
        return longest; //返回最大值
    }
};