zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 021 D

    题目链接

    题意

    给定一个字符串(S),允许修改其中至多(k)个字符变为(T)

    (T)的反转为(T'),求(T)(T')的最长公共子序列。

    题解

    结论

    (T)(T')的最长公共子序列的长度 = (T)的最长回文子序列的长度

    证明

    part. 1

    先证:(T)(T')的最长公共子序列的长度(leq T)的最长回文子序列的长度

    假设(LCS)的长度为(k),则存在(i_1<cdots <i_k)(j_1>cdots >j_k)使得(T_{i_1},T_{i_2},cdots,T_{i_k})(T_{j_1},T_{j_2},cdots,T_{j_k})是相同的。

    则必(exists p,i_p<j_p)(i_{p+1}geq j_{p+1}).(方便起见,记(i_{k+1}=|T|+1,j_{k+1}=-1).)

    1. (i_{p+1}>j_{p+1}),则序列(T_{i_1},cdots,T_{i_p},T_{j_p},cdots,T_{j_1})和序列(T_{j_k},cdots,T_{j_{p+1}},T_{i_{p+1}},cdots,T_{i_k})都是回文串,并且长度和为(2k). 因此,(T)含有一个长度至少为(k)的回文子序列;
    2. (i_{p+1}=j_{p+1}),则序列(T_{i_1},cdots,T_{i_p},T_{i_{p+1}},T_{j_p},cdots,T_{j_1})和序列(T_{j_k},cdots,T_{j_{p+2}},T_{j_{p+1}},T_{i_{p+2}},cdots,T_{i_k})都是回文串,并且长度和为(2k). 因此,(T)含有一个长度至少为(k)的回文子序列。

    part. 2

    再证:(T)(T')的最长公共子序列的长度(geq T)的最长回文子序列的长度

    假设(T)的最长回文子序列长为(k),则存在(i_1<cdots <i_k)使(T_{i_1},cdots,T_{i_k})为回文子序列。

    (j_1=n-i_k+1,cdots,j_k=n-i_1+1),则(T'_{j_1}=T{i_k}=T{i_1},cdots,T'{j_k}=T{i_1}=T{i_k}),即(T_{i_1},cdots,T_{i_k})(T'_{j_1},cdots,T'{j_k})相等,即为(T)(T')的公共子序列。

    因此,(T)(T')的公共子序列长度至少为(k).

    总结

    综上,(T)(T')(LCS)的长度 = (T)的最长回文子序列的长度。

    dp

    根据上面的结论,问题就转化成了:
    对于给定的字符串(S),修改不超过(k)个字符,使得其最长回文子序列取到最长。

    (dp[l][r][x])表示(s[l..r])修改至多(x)个字符后的最长回文子序列的长度。

    时间复杂度:(O(N^3)).

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 310
    using namespace std;
    typedef long long LL;
    char ss[maxn];
    int dp[maxn][maxn][maxn];
    int main() {
        int k;
        scanf("%s%d", ss, &k);
        int n = strlen(ss), ans=0;
        dF2(l, n-1, 0) {
            F(r, l, n) {
                F2(x, 0, k) {
                    if (ss[l]==ss[r]) dp[l][r][x] = dp[l+1][r-1][x]+(l==r?1:2);
                    else {
                        dp[l][r][x] = max(dp[l+1][r][x], dp[l][r-1][x]);
                        if (x) dp[l][r][x] = max(dp[l][r][x], dp[l+1][r-1][x-1]+2);
                    }
                }
            }
        }
        printf("%d
    ", dp[0][n-1][k]);
        return 0;
    }
    
    
  • 相关阅读:
    Spring中@Autowired注解、@Resource注解的区别 (zz)
    ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码
    jrebel
    myeclipse 上安装 Maven3
    web项目目录结构
    笔记 利用python进行数据分析
    算法浅入浅出之Textrank
    算法浅入浅出之TF-IDF
    python库之jieba小试牛刀 3
    python库之jieba小试牛刀 2
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/8470931.html
Copyright © 2011-2022 走看看