经典DP模型--回文词--IOI2000
【问题描述】
回文词是一种对称的字符串——也就是说, 一个回文词, 从左到右读和从右到左读得到的结果是一样的。 任意给定一个字符串, 通过插入若干字符, 都可以变成一个回文词。 你的任务是写一个程序, 求出将给定字符串变成回文词所需插入的最少字符数。
比如字符串“ Ab3bd”,在插入两个字符后可以变成一个回文词( “ dAb3bAd” 或“ Adb3bdA”) 。然而,插入两个以下的字符无法使它变成一个回文词。
【输入文件】
第一行包含一个整数N,表示给定字符串的长度, 3<=N<=5000
第二行是一个长度为N的字符串,字符串由大小写字母和数字构成。
【输出文件】
一个整数,表示需要插入的最少字符数。
【输入样例】
5
Ab3bd
【输出样例】
2
【问题分析】
所谓回文词(正着读和反着读一样) ,其实就是从中间断开把后面翻转后与前面部分一样(注意奇数
和偶数有区别) 。例:
回文词: AB3BA
断开: AB BA (奇数个时去掉中间字符)
翻转: AB AB
这个题目要求出最少填几个数可以使一个字符串变成回文词, 也就是说从任意点截断, 再翻转后面部分后。两个序列有相同的部分不用添字符,不一样的部分添上字符就可以了。例:
回文词: Ab3bd
截断: Ab bd
翻转: Ab db
b在两个序列里都有,在第二个里添A在第一个里添d就可以了:Adb Adb
这样添两个就可以了,
显然从别的地方截断添的个数要比这样多。这样就把原问题抽象成求最长公共子序列问题了。 枚举截断点, 把原串截断, 翻转。 求最长公共子序列。答案就是len-( ans*2) len是翻转后两个序列的长度和。 Ans 是最长公共子序列的长度。
我们注意到,另一半的LCS是和这一半的LCS相同的(另一半是指后半段不翻转,前半段翻转的两个字符串)。由此,整个字符串的LCS一定是 >= 2*ans的。
这样的话,直接把原串翻转作为第二个序列和第一个序列求最长公共子序列就可以了。这样最后求解就不用乘2了,也不用枚举截断点了例:
原串: Ab3bd
翻转: db3bA
最长公共子序列b3b
添加2个字符
怎么理解这个优化呢?
其实翻转了序列后字符的先后顺序就变了, 求解最长公共子序列中得到的解, 是唯一的, 也就是说这个序列的顺序是唯一的, 如果在翻转后的序列和原串能得到相同的序列, 那么这个序列在两个串中字符间的顺序是横定的,着就满足了回文词的定义(正着读和反着读一样) 。所以这个优化是正确的。
除了直接进行LCS的求解,更直接、变化更多的解法是进行状态划分,分析状态转移关系
原问题出发, 找这个问题的子问题。 和上面说的最长公共子序列问题一样, 设计序列的问题我们一般要考虑它的子序列,也就是更短的序列。
考虑边界条件
显然单独的字符就是边界了,而且单独的字符就是回文词,添加0个字符就可以了。
如果是两个字符组成的序列怎么办呢?
只要看他们是否相同就可以了, 如果相同那就是回文词了, 添加0个字符, 如果不相同就在它的左边
或右边添一个字符,让另外一个当对称轴。
如果是3个字符呢?
我们用S存这个序列,如果S[1]=S[3]那么它就是回文词了,
如果S[1]<>S[3]那么就在前面添S[3]或后面添S[1]
剩下的就要考虑S[1]S[2]和S[2]S[3]这两个序列了。
通过前面的分析我们很容易想到这样的算法:
对于一个序列S只要看它的左右端的字符是否相同, 如果相同那么就看除掉两端字符的新串要添的字
符个数了;如果不同,就在它左面添上右断的字符然后考虑去掉新序列两端的字符后的串要添的字符。 或
者在右面添上左端的字符,在考虑去掉添了字符后新串左右两端字符得到的新串要添的字符。
设计一个二维状态opt[L,i]表示长度是L+1, 起点是i的序列变成回文词要添的字符的个数。 阶段就是
字符的长度,决策要分类,即S[i] 和S[i+L]是否相等。
状态转移方程:
opt[L,i] =min(opt[L-1,i]+1,opt[L-1,i+1]+1) (s[i]!=s[i+L])
=min(opt[L-1,i]+1,opt[L-1,i+1]+1,opt[L-2,i+1]) (s[i]==s[i+L])
复杂度:
空间复杂度=状态数O( N2)
时间复杂度=状态数O( N2)* 转移代价O( 1)=O( N2)
扩展题目:
调整队形 (queue.pas/c/cpp) 来源: TJU P1006
【问题描述】
学校艺术节上,规定合唱队要参加比赛,各个队员的衣服颜色不能很混乱:合唱队员应排成一横排,
且衣服颜色必须是左右对称的。
例如:“ 红蓝绿蓝红” 或“ 红蓝绿绿蓝红” 都是符合的,而“ 红蓝绿红” 或“ 蓝绿蓝红” 就不符合要求。
合唱队人数自然很多,仅现有的同学就可能会有 3000个。老师希望将合唱队调整得符合要求,但想
要调整尽量少,减少麻烦。以下任一动作认为是一次调整:
1、在队伍左或右边加一个人(衣服颜色依要求而定) ;
2、在队伍中任两个人中间插入一个人(衣服颜色依要求而定) ;
3、剔掉一个人;
4、让一个人换衣服颜色;
老师想知道就目前的队形最少的调整次数是多少,请你编一个程序来回答他。
因为加入合唱队很热门, 你可以认为人数是无限的, 即随时想加一个人都能找到人。 同时衣服颜色也
是任意的。
【输入文件】
第一行是一个整数n(1≤n≤3000)。
第二行是n个整数,从左到右分别表示现有的每个队员衣服的颜色号,都是1到3000的整数。
【输出文件】
一个数,即对于输入队列,要调整得符合要求,最少的调整次数。
【输入样例】
5
122 43
【输出样例】
2
【问题分析】
读完题目发现很熟悉,仔细想想这个题就是回文词的加强版。不同与回文词的是这个问题的决策多了,不仅可以插入一个人(词) ,还可以剔人,还可以换服装,其实剔人和插入是等价的。
也就是说比原问题只多了一个条件就是可以换服装。
这样就不能用回文词的第一个方法解了。( 因为序列中的元素不固定, 可以换) 。 只能用第二个方法解。
和回文词一样,阶段是序列的长度,状态是 opt[i,j]表示[i,j]这段区间内要变成回文所需要的最少的调
整次数。
决策比回文词多了一个, 即: 如果左右两端不一样还可以通过换服装这种方式只花费一次的代价调整
好。
状态转移方程:
opt[i,j]= min{opt[i,j-1]+1,opt[i+1,j]+1,opt[i+1,j-1]+1}(a[i] != a[j],1<=i<j<=n)
= min{opt[i,j-1]+1,opt[i+1,j]+1,opt[i+1,j-1]} (a[i] == a[j],1<=i<j<=n)
边界条件:opt[i,i]=0 (1<=i<=n)
时间复杂度:
状态数O( N2)*转移代价O( 1)=总复杂度O( N2)
经典DP模型--回文词--IOI2000的更多相关文章
- 算法竞赛入门经典第二版 回文词P49
#include<bits/stdc++.h> using namespace std; char rev[]="A 3 HIL JM O 2TUVWXY51SE Z 8 &qu ...
- 回文词——线性dp
#include<iostream> #include<cstdio> using namespace std; int n,f[5002][5002]; char str1[ ...
- DP h回文子串 LCS
题目背景 IOI2000第一题 题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “A ...
- Vijos1327回文词【动态规划】
回文词 回文词是一种对称的字符串--也就是说,一个回文词,从左到右读和从右到左读得到的 结果是一样的.任意给定一个字符串,通过插入若干字符,都可以变成一个回文词.你的任务是写 一个程序,求出将给定字符 ...
- CSU 1328: 近似回文词
省赛的A题...现场都没什么人做...其实就一暴力水题......坑死了... 1328: 近似回文词 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1 ...
- 字符串 - 近似回文词 --- csu 1328
近似回文词 Problem's Link:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1328 analyse: 直接暴力枚举每一个终点,然后枚举 ...
- csuoj 1328: 近似回文词
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1328 1328: 近似回文词 Time Limit: 1 Sec Memory Limit: 1 ...
- 401 Palindromes(回文词)
Palindromes A regular palindrome is a string of numbers or letters that is the same forward as ba ...
- 回文词_KEY
回文词 (palin.pas/c/cpp) [问题描述] 回文词是一种对称的字符串--也就是说,一个回文词,从左到右读和从右到左读得的结果是一样的.任意给定一个字符串,通过插入若干字符,都可以变成一个 ...
随机推荐
- Luogu P2617 Dynamic Rankings(整体二分)
题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...
- PHP 根据整数ID,生成唯一字符串
//根据ID计算唯一邀请码 public static function createCode($Id){ static $sourceString = [ 0,1,2,3,4,5,6,7,8,9,1 ...
- Codeforces 1194B. Yet Another Crosses Problem
传送门 直接枚举填满哪一行,然后看看这一行填满以后哪一列最小 这个预处理一下 $cnt[i]$ 表示初始时第 $i$ 列有几个位置填满就可以做到 $O(m)$ 对于所有情况取个 $min$ 就是答案, ...
- 埋在 MYSQL 数据库应用中的17个关键问题!
Mysql的使用非常普遍,跟mysql有关的话题也非常多,如性能优化.高可用性.强一致性.安全.备份.集群.横向扩展.纵向扩展.负载均衡.读写分离等.要想掌握其中的精髓,可得花费不少功力,虽然目前流行 ...
- 移动端H5开发自适应技巧
移动端H5开发,必要要做到自适应各种分辨率的手机,下面由我为大家大致说一下,需要3步走 第一:head标签中添加: <meta name="viewport" content ...
- java中的异常和处理详细理解
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用System.ou ...
- Pornhub Web 开发者访谈
原文:Interview with a Pornhub Web Developer 译者:neal1991 welcome to star my articles-translator, provid ...
- Nginx如何配置https证书?
#把80端口请求跳转到443端口 server { listen 80; server_name 域名; return 301 https://$http_host$request_uri; } se ...
- python 利用已有Ner模型进行数据清洗合并
# -*- coding: utf-8 -*- from kashgari.corpus import DataReader import re from tqdm import tqdm def c ...
- 访问接口错误,com.netflix.client.ClientException: Load balancer does not have available server for client: panfeng-item-service
com.netflix.client.ClientException: Load balancer does not have available server for client: panfeng ...