牛客每日一题 合并回文子串(区间DP)

题目链接
链接: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的价值。
示例1
输入

2
aa
bb
a
aaaabcaa
输出

4
5
思路:具体细节很多大佬写的都很清楚,不了解的话可以去牛客官网找找大佬们的题解,这里就写一下自己的所获所得,由于l和r两端无法确定是否能取,这里有个巧妙地设为设dp【l】【r】【x】【y】代表a字符串的【l,r】子串和b字符串的【x,y】子串是否能构成回文,dp【x】【y】【l】【r】和dp【l】【r】【x】【y】的道理其实是一样的,但感觉自己就是很难想到这一步,有的时候还是卡在状态的定义上,不知道什么状态能不能转移,可能骨子里对动态规划还是不是很能理解。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn=55;
int T,dp[maxn][maxn][maxn][maxn];
char a[maxn],b[maxn];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        int ans=0;
        scanf("%s %s",a+1,b+1);
        int n=strlen(a+1),m=strlen(b+1);
        for(int len1=0;len1<=n;len1++)
        for(int len2=0;len2<=m;len2++)
        for(int l=1;l+len1-1<=n;++l)
        for(int x=1;x+len2-1<=m;++x)
        {
            int r=l+len1-1,y=x+len2-1;
            if(len1+len2<=1) dp[l][r][x][y]=1;
            else {
                dp[l][r][x][y]=0;
                if(len1>1) dp[l][r][x][y]|=(dp[l+1][r-1][x][y]&&a[l]==a[r]);
                if(len1&&len2) dp[l][r][x][y]|=(dp[l][r-1][x+1][y]&&a[r]==b[x]);
                if(len1&&len2) dp[l][r][x][y]|=(dp[l+1][r][x][y-1]&&a[l]==b[y]);
                if(len2>1) dp[l][r][x][y]|=(dp[l][r][x+1][y-1]&&b[x]==b[y]);
            }
            if(dp[l][r][x][y]) ans=max(ans,len1+len2);
        }
        printf("%d\n",ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值