zoukankan      html  css  js  c++  java
  • 「Luogu P1435」回文字串 解题报告

    题面

    主要大衣大意:

    给定一个字符串,求至少加入多少个字符才能使字符串变成回文字符串

    下面就是我一本正经的胡说八道题解

    思路:

    很显然,这应该是一道典型的最长公共子序列的题目

    因此,主要思想就是DP

    方程式也挺好推的

    于是我们就来讲一下为什么这题能用最长公共子序列(LCS)求解

    证明:

    求的是什么?

    想要使这个字符串加入最少的字符变成一个回文串,那么肯定就是要是字符串中不能回文的部分回文

    说起来比较难理解,比如:Ab3bd最少添的字符就是A对应的一个A,最后d对应的一个d

    我们可以发现,最少要添的字符就是不能匹配的字符数=原字符串长度len-最长回文串的长度

    这就变成了求最长回文串的题目

    怎么求?

    又经验的人肯定就会用最长公共子序列去解,但是一些人可能要问为什么,那么我们这里就来证明一下

    由于回文串是回文的(废话),也就是说,把原来的字符串反转一遍,最长回文串的长度还是不变

    于是我们就变成了求两串的公共子序列的长度——其实思想就是回文串正着和反着的效果是一样的,也就是抓住这个特性,去求公共系序列的长度

    转移方程(最好自己去推一下):

    if(a[i]==b[j])//目标状态是f[len][len]
    	f[i][j]=f[i-1][j-1]+1;//表示i,j两位置相等,那么就由i-1,j-1的状态(最优解)+1得到
    else
    	f[i][j]=max(f[i-1][j],f[i][j-1]);//否则去掉i或j,转移最优解
    

    Code:

    #include<bits/stdc++.h>
    #define N 1010
    using namespace std;
    int len;
    char a[N],b[N];
    int f[N][N];
    int main()
    {
        int i,j;
        scanf("%s",a+1);
        len=strlen(a+1);
        for(i=1;i<=len;i++)
            b[i]=a[len-i+1];//反转
        for(i=1;i<=len;i++)
            for(j=1;j<=len;j++)
                if(a[i]==b[j])
                    f[i][j]=f[i-1][j-1]+1;
                else
                    f[i][j]=max(f[i-1][j],f[i][j-1]);
        printf("%d",len-f[len][len]);//长度减去最长回文串长度
        return 0;
    }
    

    拓展知识:

    最长上升子序列(LIS)

    推荐题目(进阶,就是比较难的意思):

    【模板】最长公共子序列

  • 相关阅读:
    MongoDB +JSON+JQuery.Pagination+Linq 实现无刷新分页
    DBHelper
    C# .Net动态调用webService
    .net 将图片文件转换成流输出到浏览器
    将mongodb作为服务
    .net 最简单文件上传支持跨服务器
    Windows Phone 7
    javascript中对Date类型的常用操作
    DataTable 转换JSON
    C# 实现 MemCache 监控管理工具
  • 原文地址:https://www.cnblogs.com/hovny/p/10171998.html
Copyright © 2011-2022 走看看