动态规划:合并回文字符串

题目链接:https://ac.nowcoder.com/acm/problem/13230

题目描述


输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变。如"abc"和"xyz"可以被组合成"axbycz"或"abxcyz"等。
我们定义字符串的价值为其最长回文子串的长度(回文串表示从正反两边看完全一致的字符串,如"aba"和"xyyx")。
需要求出所有可能的C中价值最大的字符串,输出这个最大价值即可

输入描述


第一行一个整数T(T ≤ 50)。
接下来2T行,每两行两个字符串分别代表A,B(|A|,|B| ≤ 50),A,B的字符集为全体小写字母。

输出描述


对于每组数据输出一行一个整数表示价值最大的C的价值。

示例


输入#

2
aa
bb
a
aaaabcaa

输出#

4
5

分析


本题采用区间dp。
给出转移方程:
设dp[i][j][k][l] 若a[i-1]到a[j-1] 和 b[k-1]到b[l-1] 所组成的字符串是回文则其值为1,否则为2。
dp[i][j][k][l]=dp[i+1][j-1][k][l] (a[i]a[j] && i<j)
dp[i][j][k][l]=dp[i][j][k+1][l-1] (b[k]
b[l] && k<l)
dp[i][j][k][l]=dp[i+1][j][k][l-1] (a[i]b[l] && i<=j && k<=l)
dp[i][j][k][l]=dp[i][j-1][k+1][l] (a[j]
b[k] && i<=j && k<=l)
初始化:
单独一个字符显然的回文的,没有字符我们也认为它是回文的(结合转移方程)。
因此,区间长度分别设为l1,l2。初始化的条件显然 l1+l2<=1 则dp=1
另外:
注意for循环的设置。
本题中的判断为几个并列的if,因此采用了同或,任一条件触发1,即为1。

AC代码


#include <string>
#include <iostream>
#include <cstring>
using namespace std;
 
#define maxn 52
int dp[maxn][maxn][maxn][maxn];
 
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        memset(dp,0,sizeof(dp));
        string a, b;
        cin >> a >> b;
        int max = 0;
        for (int l1 = 0; l1 <= a.size(); l1++)  //枚举长度
        {
            for (int l2 = 0; l2 <= b.size(); l2++)  //枚举长度
            {
                for (int i = 1, j = l1; j <= a.size(); i++, j++)    //枚举起点
                {
                    for (int k = 1, l = l2; l <= b.size(); k++, l++)    //枚举终点
                    {
                        if (l1 + l2 <= 1)   //初始化 单个字符 空 均初始化为1
                        {
                            dp[i][j][k][l] = 1;
                        }
                        else
                        {
                            if (a[i - 1] == a[j - 1] && l1 > 1)
                                dp[i][j][k][l] |= dp[i + 1][j - 1][k][l];
                            if (b[k - 1] == b[l - 1] && l2 > 1)
                                dp[i][j][k][l] |= dp[i][j][k + 1][l - 1];
                            if (l1 && l2)
                            {
                                if (a[i - 1] == b[l - 1])
                                    dp[i][j][k][l] |= dp[i + 1][j][k][l - 1];
                                if (a[j - 1] == b[k - 1])
                                    dp[i][j][k][l] |= dp[i][j - 1][k + 1][l];
                            }
                        }
 
                        if (dp[i][j][k][l])
                            max = max > l1 + l2 ? max : l1 + l2;
                    }
                }
            }
        }
        cout << max << endl;
    }
    return 0;
}

作者:Kong Aobo

出处:https://www.cnblogs.com/kongaobo/p/14517323.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Kong-Aobo  阅读(217)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示