zoukankan      html  css  js  c++  java
  • [牛客每日一题] (区间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;
    }

    本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/15799004.html

  • 相关阅读:
    wordpress建个人博客
    函数(一)
    字符串格式化
    集合运算
    基本数据类型(二)
    基本数据类型(一)
    分享一个下片神器
    Proxyee
    基本运算符
    条件语句和while循环
  • 原文地址:https://www.cnblogs.com/Knight02/p/15799004.html
Copyright © 2011-2022 走看看