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. 使用 Knockout 扩展器扩展 observables

    原文地址:http://knockoutjs.com/documentation/extenders.html 原文名称:Using extenders to augment observables ...

  2. python中时间日期格式化符号

    python中时间日期格式化符号: import time print(time.strftime('%Y%H%M%S', time.localtime())) 运行结果: 2016092308 %y ...

  3. 关于ExpandableListView用法的一个简单小例子

    喜欢显示好友QQ那样的列表,可以展开,可以收起,在android中,以往用的比较多的是listview,虽然可以实现列表的展示,但在某些情况下,我们还是希望用到可以分组并实现收缩的列表,那就要用到an ...

  4. ASP.NET Web API实践系列04,通过Route等特性设置路由

    ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...

  5. PXE-无人值守安装

    [root@rhel6 ~]# cp /root/ks.cfg /var/ftp/ks.cfg [root@rhel6 ~]# cat ks.cfg #platform=x86, AMD64, 或 I ...

  6. SPOJ #536. How many Fibs

    Since number could be 10^100, we have to use large number processing method, in string. A simpler me ...

  7. 【SVN】win7 搭建SVN服务器

    介绍 SVN分为客户端和服务端: 服务端: 常用的主要有2个,分别为: 1. VisualSvn Server:免费,集成了Subsersion和Apache,安装使用非常简单: 2. SubVers ...

  8. 4. Median of Two Sorted Arrays

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  9. C#如何判断我的程序已经有一个实例正在运行

    static class Program { private static Mutex mutex; /// <summary> /// 应用程序的主入口点. /// </summa ...

  10. 黄聪:Discuz X2.5、3.0、3.1、3.2 如何不用插件实现用户名只允许中文注册

    1.在后台--注册与访问--注册链接文字,把“注册”改为“中文注册”或“注册(请使用中文注册)”等   2.后台UCenter管理中心---注册设置---禁止的用户名:   *q* *w* *e* * ...