问题1:插入/删除字符使得原字符串变成一个回文串且代价最小

poj 3280 Cheapest Palindrome

题意:给出一个由m中字母组成的长度为n的串,给出m种字母添加和删除花费的代价,求让给出的串变成回文串的代价。

Sol:

  • 插入和删除等价,因此只需要保留 min(插入代价,删除代价)作为调整字符串的代价
  • 如果 s[i]==s[j],那么将区间(i,j)变为回文串的代价和将区间(i+1,j-1)变为回文串的代价相同,因为此时不需要修改
  • 如果不同,必然要将 s[i]和s[j]改为同一字符
  • 第一种情况是,想要将(i,j)变为回文串,可以是在(i+1,j)已是回文串的基础上,在j后面添加字符 s[i],或者直接将i处的字符 s[i] 删掉,取代价小的操作即可
  • 另一种情况是,如果(i,j-1)是回文串,可以将j处的字符删掉或在i前面填加字符s[j],同样取代价小的方式操作

Code:提供几种不同的写法,加深理解

 #include <stdio.h>
#include <string.h>
#define mem(a) memset(a,0,sizeof(a))
#define MIN(a,b) ((a) < (b) ? (a) : (b)) int DP[][],cost[],N,M;
char str[]; int main()
{
while(~scanf("%d%d", &M, &N))
{
mem(DP); mem(str); mem(cost);
scanf("%s%*c",str);
char ch; int x, y;
for(int i=;i<M;i++)
{
scanf("%c %d %d%*c", &ch, &x, &y);
cost[ch-'a'] = MIN(x,y);
}
for(int i=;i<N;i++)
{
for(int j=i-;j>=;j--)
{
DP[j][i] = MIN(DP[j+][i]+cost[str[j]-'a'], DP[j][i-]+cost[str[i]-'a']);
if(str[i] == str[j])DP[j][i] = MIN(DP[j][i],DP[j+][i-]);
}
}
printf("%d\n", DP[][N-]);
}
return ;
}

1

     #include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int, int> P;
#define ad first
#define de second
int n, m, dp[][];
char s[];
P ch[]; //ch[ch-'a'].ad代表add一个ch的代价,ch[ch-'a'].de代表delete一个ch的代价
int main()
{
cin >> n >> m >> s;
for (int i = ; i <= n; i++)
{
char Ch;
cin >> Ch;
cin >> ch[Ch - 'a'].ad >> ch[Ch - 'a'].de;
}
for (int i = ; i <= m; i++)
dp[i][i] = ;
for (int i = ; i < m; i++) //注意for循环要实现从短串到长串的过渡,这里i代表长度为i+1
for (int j = ; j + i < m; j++)
if (s[j] == s[j + i]) dp[j][j + i] = dp[j + ][j + i - ];
else
{
int aa = dp[j + ][j + i] + min(ch[s[j] - 'a'].ad, ch[s[j] - 'a'].de);
int bb = dp[j][j + i - ] + min(ch[s[j + i] - 'a'].ad, ch[s[j + i] - 'a'].de);
dp[j][j + i] = min(aa, bb);
}
printf("%d\n", dp[][m - ]);
return ;
}

2

     #include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = ;
const int M = ;
int add[N];
int dp[M][M]; int main()
{
int n,m;
string s;
while(~scanf("%d%d",&n,&m))
{
cin>>s;
char c;int x,y;
for(int i=;i<n;i++)
{
cin>>c>>x>>y;
add[c]=min(x,y);
}
memset(dp,,sizeof(dp));
for(int k=;k<s.size();k++)
{
for(int i=,j=k;j<s.size();i++,j++)
{
dp[i][j]=0x3f3f3f3f;
if(s[i]==s[j])
dp[i][j]=dp[i+][j-];
else
{
dp[i][j]=min(dp[i+][j] + add[s[i]],dp[i][j]);
dp[i][j]=min(dp[i][j-] + add[s[j]],dp[i][j]);
}
}
}
printf("%d\n",dp[][s.size()-]);
}
return ;
}

3


问题2:插入最少多少个字符使得原字符串变成一个回文串

poj 1159 Palindrome

Sol:

首先第一种方法是:

这道题相当于是上一个题中的修改代价为1的情况

因此列出方程:

从上面的分析可以看出,这个问题的实质是求最长公共子序列,只是这两个序列分别是串S的前一部分和串S后一部分的逆序列。

由此引出第二种方法

第二种方法:

先说结论:设原序列S的逆序列为S',最少需要补充的字母数 = 原序列S的长度-S和S'的最长公共子串长度

最后这道题需要对内存进行优化

Code:

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAXSIZE 5005 //开始没有考虑内存问题,使用了int型,超内存限制,也可使用滚动数组解决
unsigned short d[MAXSIZE][MAXSIZE]; int ToPalindrome(char *s, int n)
{
int i, j, k;
//只有一个字符时,不需要添加字符
for (i = ; i < n; i++)
{
d[i][i] = ;
}
//串长度为2时
for (i = ; i < n; i++)
{
if (s[i-] == s[i])
{
d[i-][i] = ;
}
else
{
d[i-][i] = ;
}
} //串长度递增
for (k = ; k < n; k++)
{
for (i = , j = k; j < n; i++, j++)
{
if (s[i] == s[j])
{
d[i][j] = d[i+][j-];
}
else
{
d[i][j] = MIN(d[i][j-], d[i+][j]) + ;
}
}
}
return d[][n-];
} int main(void)
{
char str[MAXSIZE]; int n;
while (scanf("%d", &n) != EOF)
{
getchar();
gets(str);
printf("%d\n", ToPalindrome(str, n));
}
return ;
}

1

 #include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std; const int N=;
int n;
char a[N],b[N];
int f[][N]; int main(){
while(scanf("%d",&n)!=EOF){
scanf("%s",a+);
for(int i=;i<=n;++i)
b[i]=a[n-i+];
memset(f,,sizeof(f));
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
if(a[i]==b[j]) f[i%][j]=f[(i-)%][j-]+;
else f[i%][j]=max(f[(i-)%][j],f[i%][j-]);
printf("%d\n",n-f[n%][n]);
}
return ;
}

2

关于回文串的DP问题的更多相关文章

  1. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...

  2. 回文串 --- 动态dp UVA 11584

    题目链接: https://cn.vjudge.net/problem/34398/origin 本题的大意其实很简单,就是找回文串,大致的思路如下: 1. 确定一个回文串,这里用到了自定义的chec ...

  3. poj3280 Cheapest Palindrome(回文串区间dp)

    https://vjudge.net/problem/POJ-3280 猛刷简单dp第一天第三题. 这个据说是[求字符串通过增减操作变成回文串的最小改动次数]的变体. 首先增减操作的实质是一样的,所以 ...

  4. 1154 回文串划分(DP+Manacher)

    1154 回文串划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一个字符串S,求S最少可以被划分为多少个回文串. 例如:abbaabaa,有多种划分方式. ...

  5. uva 10453 【回文串区间dp】

    Uva 10453 题意:给定字符串,问最少插入多少个字符使其变成回文串,并任意输出一种结果. 题解:和Uva 10739类似,这里是只能增加.类似定义dp[i][j]表示子串Si...Sj变为回文串 ...

  6. [LeetCode] Palindrome Partitioning 拆分回文串

    Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...

  7. 计蒜之道 初赛 第三场 题解 Manacher o(n)求最长公共回文串 线段树

    腾讯手机地图 腾讯手机地图的定位功能用到了用户手机的多种信号,这当中有的信号的作用范围近.有的信号作用的范围则远一些.有的信号相对于用户在不同的方位强度是不同的,有的则是在不论什么一个方向上信号强度都 ...

  8. NYOJ 1023 还是回文(DP,花最少费用形成回文串)

    /* 题意:给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费. 那么,将字符串变成回文串的最小花费是多少呢? 思路:如果一个字符串增加一个字符 x可以形成一个回文串,那么从这个字 ...

  9. poj 1159 dp回文串

    题意:添加最少的字符使之成为回文串 #include<cstdio> #include<iostream> #include<algorithm> #include ...

随机推荐

  1. [C++]智能指针的实现与使用

    智能指针 智能指针是当我们在使用对象时,有时会把对象的内存分配在堆上忘记释放,导致内存泄露,并且当多个指针共享同一个对象的内存时,容易出现重复释放内存,导致错误. 我们针对所需要共享的对象,手动完成一 ...

  2. Python爬取百度贴吧数据

    本渣除了工作外,在生活上还是有些爱好,有些东西,一旦染上,就无法自拔,无法上岸,从此走上一条不归路.花鸟鱼虫便是我坚持了数十年的爱好. 本渣还是需要上班,才能支持我的业余爱好.上班时间还是尽量访问外网 ...

  3. 【CSS3】使用CSS3线性渐变实现图片闪光划过效果(转)

    原文:http://www.nowamagic.net/librarys/veda/detail/2600 资料参考: http://www.cnblogs.com/lhb25/archive/201 ...

  4. 【Mysql】Mysql关键字

    ADD ALL ALTER ANALYZE AND AS ASC ASENSITIVE BEFORE BETWEEN BIGINT BINARY BLOB BOTH BY CALL CASCADE C ...

  5. web前端开发面试题(未完待续)

    一.HTML与XHTML的不同:1)XHTML元素必须被正确地嵌套 2)元素必须被关闭   如:<h1>--</h1>关闭 3)标签名必须用小写字母 4)XHTML文档必须有根 ...

  6. Spring核心--IOC

    先说说Spring框架 Spring框架 Spring框架的作用 Spring 的核心(IOC功能) SpringAOP功能 原有的业务流程:请求->servlet-->service-- ...

  7. 教你上传本地代码到github

    最近想起学Git,并且注册了Github. 将新创建的本地代码上传到github上,这里简单的记录一下,我喜欢使用命令行,这里全用命令行来实现,不了解Git命令的可以去了解下. 第一步:建立git仓库 ...

  8. Hibernate的系统 学习

    Hibernate的系统 学习 一.Hibernate的介绍 1.什么是Hibernate? 首先,hibernate是数据持久层的一个轻量级框架.数据持久层的框架有很多比如:iBATIS,myBat ...

  9. ubuntu中ssh自启动

    打开/etc/rc.local文件,在exit 0语句前加入: /etc/init.d/ssh start(前提是本身的启动方法是这样的才可以) 或者/usr/local/sbin/sshd(我使用的 ...

  10. swift3.0 点击UIScrollView中输入框之外的区域关闭键盘

    通过点击事件实现关闭键盘 scrollView: UIScrollView! title_textField: UITextField! let hideKeyboardTapGesture = UI ...