d.求对字符串最少添加几个字符可变为回文串。

s.

法1:直接对它和它的逆序串求最长公共子序列长度len。N-len即为所求。(N为串长度)

因为,要求最少添加几个字符,我们可以先从原串中找到一个最长回文子序列,然后对于原串中不属于这个回文子序列的字符,在串中的相应位置添加一个相同的字符即可。那么需要添加的字符数量即为N-len。

最长回文串可以看作是原串中前面和后面字符的一种匹配(每个后面的字符在前面找到一个符合位置要求的与它相同的字符)。这种的回文匹配和原串与逆序串的公共子序列是一一对应的(一个回文匹配对应一个公共子序列,反之亦然),而且两者所涉及到的原串中的字符数量是相等的,也就是最长公共子序列对应最长回文串。原因陈述完毕。

dp[i][j]表示原串前i个字符与逆序串前j个字符的最长公共子序列

if(str[i-1]==str2[j-1]){
  dp[i][j]=dp[i-1][j-1]+1;
}
else{
  dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}

法2:

dp[i][j]表示从i到j这段子串若变为回文串最少添加的字符数。

if(str[i]==str[j]){
  dp[i][j]=dp[i+1][j-1];
}
else{
  dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1;
}

c.法1

/*
用short险过 dp[i][j]表示原串前i个字符与逆序串前j个字符的最长公共子序列 if(str[i-1]==str2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
} */
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define MAXN 5005 short dp[MAXN][MAXN];
char str[MAXN],str2[MAXN]; int main(){ int N;
int i,j; while(~scanf("%d",&N)){ scanf("%s",str); for(i=,j=N-;i<N;++i,--j){
str2[i]=str[j];
} memset(dp,,sizeof(dp));
for(i=;i<=N;++i){
for(j=;j<=N;++j){
if(str[i-]==str2[j-]){
dp[i][j]=dp[i-][j-]+;
}
else{
dp[i][j]=max(dp[i-][j],dp[i][j-]);
}
}
} printf("%d\n",N-dp[N][N]);
} return ;
}

ps:其实可以用滚动数组

c'.滚动数组

/*
用short险过 dp[i][j]表示原串前i个字符与逆序串前j个字符的最长公共子序列 if(str[i-1]==str2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
} */
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define MAXN 5005 short dp[][MAXN];//滚动数组
char str[MAXN],str2[MAXN]; int main(){ int N;
int i,j; while(~scanf("%d",&N)){ scanf("%s",str); for(i=,j=N-;i<N;++i,--j){
str2[i]=str[j];
} memset(dp,,sizeof(dp));
for(i=;i<=N;++i){
for(j=;j<=N;++j){
if(str[i-]==str2[j-]){
dp[i%][j]=dp[(i-)%][j-]+;
}
else{
dp[i%][j]=max(dp[(i-)%][j],dp[i%][j-]);
}
}
} printf("%d\n",N-dp[N%][N]);
} return ;
}

c2.法2

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define MAXN 5005 short dp[MAXN][MAXN];
char str[MAXN]; int main(){ int N;
int i,j; while(~scanf("%d",&N)){
scanf("%s",str); memset(dp,,sizeof(dp)); for(i=N-;i>=;--i){
dp[i][i]=;
for(j=i+;j<N;++j){
if(str[i]==str[j]){
dp[i][j]=dp[i+][j-];
}
else{
dp[i][j]=min(dp[i+][j],dp[i][j-])+;
}
}
} printf("%d\n",dp[][N-]);
} return ;
}

c2'.滚动数组

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define MAXN 5005 short dp[][MAXN];//滚动数组
char str[MAXN]; int main(){ int N;
int i,j; while(~scanf("%d",&N)){
scanf("%s",str); memset(dp,,sizeof(dp)); for(i=N-;i>=;--i){
dp[i%][i%]=;
for(j=i+;j<N;++j){
if(str[i]==str[j]){
dp[i%][j]=dp[(i+)%][j-];
}
else{
dp[i%][j]=min(dp[(i+)%][j],dp[i%][j-])+;
}
}
} printf("%d\n",dp[][N-]);
} return ;
}

POJ - 1159 Palindrome(dp-回文变形)的更多相关文章

  1. POJ 3280 Cheapest Palindrome(DP 回文变形)

    题目链接:http://poj.org/problem?id=3280 题目大意:给定一个字符串,可以删除增加,每个操作都有代价,求出将字符串转换成回文串的最小代价 Sample Input 3 4 ...

  2. poj 3280 Cheapest Palindrome ---(DP 回文串)

    题目链接:http://poj.org/problem?id=3280 思路: dp[i][j] :=第i个字符到第j个字符之间形成回文串的最小费用. dp[i][j]=min(dp[i+1][j]+ ...

  3. HDU 1513 && POJ 1159 Palindrome (DP+LCS+滚动数组)

    题意:给定一个字符串,让你把它变成回文串,求添加最少的字符数. 析:动态规划是很明显的,就是没有了现思路,还是问的别人才知道,哦,原来要么写,既然是回文串, 那么最后正反都得是一样的,所以我们就正反求 ...

  4. poj 1159 Palindrome(dp)

    题目:http://poj.org/problem?id=1159 #include<iostream> #include<cstring> #include<cstdi ...

  5. poj 1159 最长回文

    方法  LCS #include<iostream> #include<cstring> #include<algorithm> #include<stdio ...

  6. POJ 1159 Palindrome(字符串变回文:LCS)

    POJ 1159 Palindrome(字符串变回文:LCS) id=1159">http://poj.org/problem? id=1159 题意: 给你一个字符串, 问你做少须要 ...

  7. CF932G Palindrome Partition(回文自动机)

    CF932G Palindrome Partition(回文自动机) Luogu 题解时间 首先将字符串 $ s[1...n] $ 变成 $ s[1]s[n]s[2]s[n-1]... $ 就变成了求 ...

  8. [LeetCode] Valid Palindrome 验证回文字符串

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  9. dp回文

    .dp回文子串 通常在dp数组中存放的是 从i到j是否是回文子串 1.动态规划 2.中心扩展法 #include<iostream> #include<algorithm> # ...

随机推荐

  1. python之路 之open

    一.open:文件打开操作 文件句柄 = open('文件路径','读写模式') 打开文件的模式有: r:只读,默认(文件不存在则报错) w:只写(文件不存在则自动创建) a:追加(文件不存在则自动创 ...

  2. JAVA除法保留小数点后两位的两种方法 Java Math的 floor,round和ceil的总结

    floor 返回不大于的最大整数 round 则是4舍5入的计算,入的时候是到大于它的整数round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下 ...

  3. Android视录视频示例

    这几天需要搞一个Android视频通话功能,从最简单的视频录制开始,网上例子大多不完整.下面的示例参考过别人的代码,还是拿出来给需要的朋友分享下. Activity类:VideoActivity pa ...

  4. 找不到所需要的ndbm.h头文件

    具体描述: 通过deb包安装gdbm之后,发现找不到所需要的ndbm.h头文件.但是你会发现一个叫gdbm-ndbm.h的文件,你只需要把文件名改成ndbm.h就可以了,当然需要一定权限. sudo ...

  5. Oracle的rownum原理和使用

    整理和学习了一下网上高手关于rownum的帖子: 参考资料:  http://tech.ddvip.com/2008-10/122490439383296.html 和 http://tenn.jav ...

  6. Anaconda多环境多版本python配置指导

    Anaconda多环境多版本python配置指导 字数3696 阅读644 评论0 喜欢0 最近学python,读完了语法后在GitHub找了一些练习来做,由 于学的是python3.x语法,而Git ...

  7. 【linux】/etc/passwd文件

    /etc/passwd文件内容格式 /etc/passwd是保存用户信息的文件. 格式:用户名: 密码 : uid  : gid :用户描述:主目录:登陆shell 举个例子: root:x:0:0: ...

  8. (转)[SQL Server] 动态sql给变量赋值(或返回值给变量)

    本文转载自:http://blog.csdn.net/xiaoxu0123/article/details/5684680 [SQL Server] 动态sql给变量赋值(或返回值给变量) decla ...

  9. lwip:网络数据包读取和解析过程

    1. 程序的某处(poll or interrupt)在有数据可读时调用ethernetif_input,该函数依次调用以下函数: 1.1 low_level_input(),将网络数据读入内存: 1 ...

  10. db4o种纯对象数据库引擎

    db4o是一种纯对象数据库,相对于传统的关系数据库+ORM,db4o具有以下好处:1)以存对象的方式存取数据(废话--,不过你考虑一下完全以对象的方式去考虑数据的存取对传统的数据库设计思维来说是多么大 ...