[牛客每日一题] (区间DP)[最长回文子序列] NC13230 合并回文子串

合并回文子串 (nowcoder.com)icon-default.png?t=LA92https://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

在此用f[i][j][k][l]表示从字符串a中取出第i个到第j个字符间的子串和从字符串b中取出第k个到第l个字符间的子串是否满足回文串

何为小区间?

这里的最小的区间,无疑是边界,当出现f[i][i][k][k]的时候,即取的两个串的长度小于等于1时, 如果此时又恰好a[i]==b[k]的话, f数组取值可为1

如何利用小区间更新大区间呢?

以下任一种合理,最终f取值就为真

区间dp要从短区间扩展到长区间,所以如果不是使用记忆化搜索的话,就需要按区间长短来枚举而不是直接枚举首末端点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 55;
bool f[N][N][N][N];
char a[N], b[N];

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        scanf("%s", a+1);
        scanf("%s", b+1);
        int la = strlen(a + 1);
        int lb = strlen(b + 1);
        int res = 0;
        for(int l1 = 0; l1 <= la; l1 ++)        //枚举a串的长度
            for(int l2 = 0; l2 <= lb; l2 ++)    //枚举b串的长度
                for(int i = 1; i+l1-1 <= la; i ++)
                    for(int k = 1; k+l2-1 <= lb; k ++)
                    {
                        int j = i+l1-1, l = k+l2-1;
                        if(l1+l2 <= 1) 
                            f[i][j][k][l] = 1;
                        else{
                            f[i][j][k][l] = 0;
                            if(l1 > 1) f[i][j][k][l] |= ((a[i]==a[j]) && f[i+1][j-1][k][l]);
                            if(l2 > 1) f[i][j][k][l] |= ((b[k]==b[l]) && f[i][j][k+1][l-1]);
                            if(l1 && l2){
                                f[i][j][k][l] |= ((a[i]==b[l]) && f[i+1][j][k][l-1]);
                                f[i][j][k][l] |= ((a[j]==b[k]) && f[i][j-1][k+1][l]);
                            }
                        }
                        
                        if(f[i][j][k][l]){
                            res = max(res, l1+l2);
                        }
                    }
        cout << res << endl;
;    }
    return 0;
}

posted @ 2021-12-25 23:28  泥烟  阅读(50)  评论(0编辑  收藏  举报