leetcode 3504 回文+最长公共子数组

题目的拆解很重要,我们先把 s 2 s2 s2 反过来,即我们先要找到 s 1 s1 s1 和 s 2 s2 s2 最长公共子串,再找到 s 1 s1 s1 中结尾的最长回文串。

定义 d p 1 [ i ] dp1[i] dp1[i] 为 s 1 s1 s1 中以 i i i 开头的最长回文串长度

定义 d p 3 [ i ] dp3[i] dp3[i] 为 s 1 s1 s1 中以 i i i 结尾的最长后缀长度

那么,我们只需要枚举 s 1 s1 s1 中每个字符即可,代码如下:

注:是否要用 # 进行额外操作?其实是不用的,因为额外考虑两个元素并列的情况,不需要花费太多代码,# 和最长后缀数组加起来,反而会有额外的边界情况,故不建议这么做。

cpp 复制代码
typedef vector<int> V;
class Solution {
public:
    int process(string& s1, string& s2){
        // 设计dp1数组,dp1[i] = s1 i元素开头的最长回文子串长度
        int n1 = s1.size(), n2 = s2.size();
        vector<int> dp1(n1, 1);
        for(int i=0;i<n1;i++){
            // case 1
            for(int j=1;j<=n1;j++){
                int l = i-j, r = i+j;
                if(l < 0 or r >= n1)break;
                if(s1[l] != s1[r])break;
                if(r-l+1 > dp1[l])dp1[l] = r-l+1;
            }
            // case2
            if(i+1 < n1 and s1[i] == s1[i+1]){
                if(dp1[i] < 2)dp1[i] = 2;
                for(int j=1;j<=n1;j++){
                    int l = i-j, r = i+1+j;
                    if(l < 0 or r >= n1)break;
                    if(s1[l] != s1[r])break;
                    if(r-l+1 > dp1[l])dp1[l] = r-l+1;
                }
            }
        }

        // 设计dp2数组,dp2[i][j] = s1 i-1下标结尾,s2 j-1下标结尾的最长后缀长度
        // 设计dp3数组,dp3[i] = s1 i下标结尾的最长后缀长度
        vector<V> dp2(n1+1, V(n2+1, 0));
        V dp3(n1, 0);

        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++){
                if(s1[i-1] == s2[j-1]){
                    dp2[i][j] = dp2[i-1][j-1] + 1;
                    if(dp2[i][j] > dp3[i-1])dp3[i-1] = dp2[i][j];
                }
                else dp2[i][j] = 0;
            }
        }

        // 遍历s1 0 - n1-1,取到最大数组的开头和结尾
        int max_len = 0, ans = 0;
        for(int i=0;i<=n1;i++){
            int l = 0, r = 0;
            if(i-1 >= 0 and i-1 < n1)l = dp3[i-1]*2;
            if(i >= 0 and i < n1)r = dp1[i];
            if(l+r > max_len){
                max_len = l+r;
            }
        }

        return max_len;
    }

    int longestPalindrome(string s, string t) {
        reverse(t.begin(), t.end());
        return max(process(s, t), process(t, s));
    }
};
相关推荐
xin007hoyo3 小时前
算法笔记·数学·最大公约数
笔记·算法
丶Darling.4 小时前
Day126 | 灵神 | 二叉树 | 层数最深的叶子结点的和
数据结构·c++·算法·二叉树·深度优先
是麟渊4 小时前
【大模型面试每日一题】Day 27:自注意力机制中Q/K/V矩阵的作用与缩放因子原理
人工智能·线性代数·自然语言处理·面试·职场和发展·架构
小O的算法实验室4 小时前
2025年ESWA SCI1区TOP,离散人工蜂群算法+多农场多除草机器人任务分配,深度解析+性能实测
算法·智能算法改进
2401_859049085 小时前
Git使用
arm开发·git·stm32·单片机·mcu·算法
冠位观测者6 小时前
【Leetcode 每日一题】2942. 查找包含给定字符的单词
算法·leetcode·职场和发展
蓝心湄6 小时前
C语言-枚举
c语言·开发语言·算法
轮到我狗叫了6 小时前
力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法
算法·leetcode·深度优先
黎明smaly6 小时前
【C语言】复习~数组和指针
c语言·开发语言·数据结构·c++·leetcode
haven-8527 小时前
最大似然估计(Maximum Likelihood Estimation, MLE)详解
算法·机器学习·概率论