问题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. luogu P1361 小猫爬山 [iddfs]

    题目描述 WD和LHX饲养了N只小猫,这天,小猫们要去爬山.经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了. WD和LHX只好花钱让它们坐索道下山.索道上的缆车最大承重量为W ...

  2. servlet前台中文参数处理

    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletExcep ...

  3. java 常见数据结构

    1)tree 2) queue 3) list 4) stack 5) heap 6) map

  4. 40. leetcode 202. Happy Number

    Write an algorithm to determine if a number is "happy". A happy number is a number defined ...

  5. 笔记本电脑连接上WiFi后,弹不出登录界面怎么办?

    以CMCC为例子 步骤: 1 连接成功CMCC之后,打开适配器设置.右击无线网卡,选择属性 2.双击INTERNET协议版本4 3.将DNS改成自动获取,然后确定 4.再确定 5.然后重新断开CMCC ...

  6. C#和NewSQL更配 —— CockroachDB入门(可能是C#下的全网首发)

    阅读目录 CockroachDB是什么 环境部署 实战 性能测试 结语 一.CockroachDB是什么 CockroachDB(https://www.cockroachlabs.com)是Goog ...

  7. solr排序问题

         搜搜引擎排序问题,因为涉及到的维度比较多,有时候单纯的依靠sort是无法满足需要的,例如:搜索商品的时候我希望不管怎么排无货的商品都置底,这样问题就来了,怎么排? 其实,solr是自己的解决 ...

  8. 阅读:DBA们不得不知的数据库硬件RAID常识

    对于数据库这种特殊应用IOPS往往会成为瓶颈,突破的这个瓶颈的有效方法不多,软件方面主要是读写分离,垂直拆分,分区表技术,cluster.硬件方面主要是raid,和SSD. 通常都是软件和硬件同时优化 ...

  9. 切换Ubuntu系统python默认版本的方法

    另附切换系统python默认版本的方法: 先使用命令: update-alternatives --list python 查看python命令的各种可能结果, 例如我的结果: /usr/bin/py ...

  10. SQL查询操作及子句优先级

    用source .sql文件竟然可以自动建表. 简单数据查询: select * from table_name; 避免重复查询: select distinct(field_name) from t ...