• 【每日一题】2.合并回文子串 (字符串处理 + 区间DP)


    题目链接:Here

    遇到这种数据范围较小的计数问题应该优先考虑dp,本题就是如此。
    那么应该怎么样考虑转移呢?
    首先最后C中的那个价值最大的子串一定是由字符串A的一个区间和字符串B的一个区间合并得到的,
    那么现在假设 A[i] ~ A[j]B[k] ~ B[l] 构成了一个回文串(这里设 dp[i][j][k][l])

    则他能转移到的区间有
    1:(a[i-1]==a[j+1] 时 dp[i-1][j+1][k][l])
    2:(a[i-1]==b[l+1]时 dp[i-1][j][k][l+1])
    3:(b[k-1]==a[j+1]时 dp[i][j+1][k-1][l])
    4:(b[k-1]==b[l+1]时 dp[i][j][k-1][l+1])

    那么对于的转移方程也就是:

    if (a[i] == a[j]) dp[i][j][k][l] |= dp[i + 1][j - 1][k][l];
    if (b[k] == b[l]) dp[i][j][k][l] |= dp[i][j][k + 1][l - 1];
    if (a[i] == b[l]) dp[i][j][k][l] |= dp[i + 1][j][k][l - 1];
    if (a[j] == b[k]) dp[i][j][k][l] |= dp[i][j - 1][k + 1][l];
    

    然后就可以轻松的区间转移啦~~~~~
    oh,在注意一下枚举过程中只有一个字母的状态一定是回文的就可以啦

    AC 代码

    // Murabito-B 21/04/06
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    int dp[60][60][60][60];
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(0);
        int _;
        for (cin >> _; _--;) {
            string a, b;
            cin >> a >> b;
            a = "@" + a, b = "@" + b;
            int lena = a.size(), lenb = b.size();
            int ans = 0;
            for (int l1 = 0; l1 <= lena; ++l1)
                for (int l2 = 0; l2 <= lenb; ++l2)
                    for (int i = 1; i <= lena - l1; ++i)
                        for (int k = 1; k <= lenb - l2; ++k) {
                            int j = i + l1 - 1, l = k + l2 - 1;
                            // 说明此时仅一个点
                            if (l1 + l2 <= 1) dp[i][j][k][l] = 1;
                            else {
                                dp[i][j][k][l] = 0;
                                if (a[i] == a[j]) dp[i][j][k][l] |= dp[i + 1][j - 1][k][l];
                                if (b[k] == b[l]) dp[i][j][k][l] |= dp[i][j][k + 1][l - 1];
    
                                if (a[i] == b[l]) dp[i][j][k][l] |= dp[i + 1][j][k][l - 1];
                                if (a[j] == b[k]) dp[i][j][k][l] |= dp[i][j - 1][k + 1][l];
                            }
                            if (dp[i][j][k][l]) ans = max(ans, l1 + l2);
                        }
            cout << ans << "
    ";
        }
        return 0;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    编码问题
    Linux环境给文件重命名
    FIFO简记
    图像去模糊
    matlab直方图均衡,使用向量优化
    研究方向
    FPGA学习笔记之格雷码、边沿检测、门控时钟
    [转]关于凸优化的一些简单概念
    SSD果然劲爆!
    Qunie问题
  • 原文地址:https://www.cnblogs.com/RioTian/p/14621802.html
Copyright © 2020-2023  润新知