关于回文串的DP问题
问题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问题的更多相关文章
- 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)
[GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...
- 回文串 --- 动态dp UVA 11584
题目链接: https://cn.vjudge.net/problem/34398/origin 本题的大意其实很简单,就是找回文串,大致的思路如下: 1. 确定一个回文串,这里用到了自定义的chec ...
- poj3280 Cheapest Palindrome(回文串区间dp)
https://vjudge.net/problem/POJ-3280 猛刷简单dp第一天第三题. 这个据说是[求字符串通过增减操作变成回文串的最小改动次数]的变体. 首先增减操作的实质是一样的,所以 ...
- 1154 回文串划分(DP+Manacher)
1154 回文串划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一个字符串S,求S最少可以被划分为多少个回文串. 例如:abbaabaa,有多种划分方式. ...
- uva 10453 【回文串区间dp】
Uva 10453 题意:给定字符串,问最少插入多少个字符使其变成回文串,并任意输出一种结果. 题解:和Uva 10739类似,这里是只能增加.类似定义dp[i][j]表示子串Si...Sj变为回文串 ...
- [LeetCode] Palindrome Partitioning 拆分回文串
Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...
- 计蒜之道 初赛 第三场 题解 Manacher o(n)求最长公共回文串 线段树
腾讯手机地图 腾讯手机地图的定位功能用到了用户手机的多种信号,这当中有的信号的作用范围近.有的信号作用的范围则远一些.有的信号相对于用户在不同的方位强度是不同的,有的则是在不论什么一个方向上信号强度都 ...
- NYOJ 1023 还是回文(DP,花最少费用形成回文串)
/* 题意:给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费. 那么,将字符串变成回文串的最小花费是多少呢? 思路:如果一个字符串增加一个字符 x可以形成一个回文串,那么从这个字 ...
- poj 1159 dp回文串
题意:添加最少的字符使之成为回文串 #include<cstdio> #include<iostream> #include<algorithm> #include ...
随机推荐
- maven-编译速度优化
故障描述: 公司搭建了一个新jenkins持续集成环境,jenkins构建job时间越来越长. 原因分析: 系统CPU限制:判断依据,构建中查看日志 tail -f /var/log/messages ...
- (转)Linux下增加交换分区的大小
场景:最近在Linux环境安装ELK相关软件时候发现机器特别的卡,所以就查看了Linux机器的内存使用情况,发现是内存和交换分区空间太小了. 对于虚拟机中的内存问题,可以直接通过更改虚拟机的硬件进行解 ...
- 【css】css3属性
1. 无需区分webkit moz等前缀的css3属性 text-shadow background 2. 需要区分前缀的css属性 border-radius box-shadow text-str ...
- 二.GC相关之Java内存模型
根据上节描述的问题,我们知道其最终原因是GC导致的.本节我们就先详细探讨下与GC息息相关的Java内存模型. 名词解释:变量,理解为java的基本类型.对象,理解为java new出来的实例. Jav ...
- if else 和switch case以及continue,break的区别
1,if 经常用于做区间判断 或者 固定值: break和continue的使用 break:用来结束循环结构或者switch case continue:结束此次循环进入 ...
- 接口工具-POSTMAN
前端的一项总要工作就是测试接口,当然这也可能是你们后台人员做的.不管怎样,都需要测试接口,那么就来介绍一款谷歌浏览器接口测试插件,postman.首先你要去谷歌的应用商店,搜索这个插件,(需要FQ), ...
- Python用Pillow(PIL)进行简单的图像操作
Python用Pillow(PIL)进行简单的图像操作 颜色与RGBA值 计算机通常将图像表示为RGB值,或者再加上alpha值(通透度,透明度),称为RGBA值.在Pillow中,RGBA的值表示为 ...
- Android中的内容提供者
Android中的内容提供者 为什么需要内容提供者 为了跨程序访问数据.试想如果在App-1中创建了一个私有数据库,App-2是不能直接访问的.因为权限不够,虽然可以使用chmod 777来修改权限, ...
- 引水入城[NOI2010 ]
题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度. 为了 ...
- MySql 使用 EF Core 2.0 CodeFirst、DbFirst、数据库迁移(Migration)介绍及示例
dotnet core 2.0 发布已经好几天了,期间也把原来 dotnet core 1.1 的 MVC 项目升级到了 2.0,升级过程还是比较顺利的,变动也不是太多.升级的过程中也少不了 Enti ...