Loading

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

题目链接: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;
}
posted @ 2021-03-11 13:30  Kong-Aobo  阅读(210)  评论(0编辑  收藏  举报