P1435 回文字串
P1435 回文字串
题目背景
IOI2000第一题
题目描述
回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。
比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。
注:此问题区分大小写
输入输出格式
输入格式:
一个字符串(0<strlen<=1000)
输出格式:
有且只有一个整数,即最少插入字符数
输入输出样例
Ab3bd
2
分析:
解题思路:该题说是考察如何将一个字符串添加成一个回文串的,不如说是一道求最长公共自序列的变式题,为啥这么说呢?肯定是有原因在里面的
首先,我们要摸清回文串的特性,回文就是正着读反着读一样,一种非常对称不会逼死强迫症的字符串;这就是我们的突破口。。。你难道以为是逼死强迫症么?哈哈,太天真了,突破口其实是因为回文正着读反着读都相同的特性。。。这样我们就可以再建一个字符数组存储倒序的字符串
- 我们先分析下样例:ab3bd,
它的倒序是:db3ba
这样我们就可以把问题转化成了求最长公共自序列的问题,为啥可以这么转化呢?
它可以这么理解,正序与倒序“公共”的部分就是我们回文的部分,如果把正序与倒序公共的部分减去你就会惊奇的发现剩余的字符就是你所要添加的字符,也就是所求的正解
ad da把不回文的加起来就是我们梦寐以求的东西:回文串(卧槽?太没追求了)
把ad,da加起来成回文串就是adb3bda,所以这个问题就可以转化成了求最长公共自序列的问题,将字符串的长度减去它本身的“回文的”(最长公共自序列)字符便是正解
- 找到解题思路后我们就可以开始写了,最长公共自序列问题是个经典的dp问题,
最容易想到的方法就是开个二维数组dp【i】【j】,i,j分别代表两种状态;
那么我们的动态转移方程应该就是if(str1[i] == str2[j]) dp[i][j]=dp[i-1][j-1]+1;
Else dp[i][j] = max(dp[i-1][j], dp[i][j-1];
依此即可解出最长公共自序列,用字符串长度减去即是正解
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
int n;
int dp[][];
char str1[],str2[];
int main()
{
//freopen("palindrome.in", "r", stdin);
//freopen("palindrome.out", "w", stdout);
scanf("%s", str1+);
n = strlen(str1+);
for(int i = ; i <= n; i++)
str2[i] = str1[n-i+]; //做一个逆序的字符串数组
for(int i = ; i<=n; i++)
for(int j = ; j <= n; j++)
if(str1[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 ; //即需要添加的字符数
}
可这并不是最优解法,只是能ac这道题而已 若是将内存限制改为2MB呢?
不过,没关系,正常开一个5001*5001的数组一定会爆掉的,此时你是不是在思考另一种解决方案来优化一下空间复杂度,如果我可以把它用一维数组代替二维数组中的状态量是不是也可以求出正解
没错。它真的能
求出正解;
如果你仔细研究一下就会发现每次搜索到str1的第i个元素的时候,数组dp【】【】真正使用到的元素仅仅是dp【i】【j】和dp【i-1】【k】(0 <= k <= n(n = strlen(str1))
即dp【】【】的第一下标从0-->i-2就没有用处了,因此我们可以开辟两个滚动数组来降低空间复杂度
Dp1【】用来记录当前状态,dp2【】用来记录之前的状态也就相当于刚才的dp【i-1】【j】
动态转移方程应该这么表达if(str1[i] == str2[i]) dp1[j] = dp2[j-1] +1;
Else dp1[j] = max(dp1[j-1], dp2[j]);
源代码在此,天下我有:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
int n;
int dp1[],dp2[]; //此处用两个滚动数组记录,一个记录之前的状态,一个记录此时的状态
char str1[],str2[];
int main()
{
//freopen("palindrome.in", "r", stdin);
//freopen("palindrome.out", "w", stdout);
scanf("%s", str1+);
n = strlen(str1+);
for(int i = ; i <= n; i++)
str2[i] = str1[n-i+]; //做一个逆序的字符串数组
for(int i = ; i<=n; i++)
{
for(int j = ; j <= n; j++)
if(str1[i] == str2[j])
dp1[j] = dp2[j-]+; //“发现”匹配就记录
else
dp1[j] = max(dp1[j-],dp2[j]); //不匹配就匹配后面的状态
memcpy(dp2, dp1, sizeof(dp1)); //记录之前的状态“滚动”匹配
}
printf("%d\n", n-dp1[n]); //字符串长度减去匹配出的最长公共自序列的值
return ; //即需要添加的字符数
}
ps:
滚动数组交换的时候,感觉直接交换索引比直接交换dp1和dp2整个数组要优。
P1435 回文字串的更多相关文章
- P1435 回文字串(LCS问题)
题目背景 IOI2000第一题 题目描述(题目链接:https://www.luogu.org/problem/P1435) 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成 ...
- 洛谷P1435 回文字串(dp)
题意 题目链接 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “Ab3bd”插入2个字符后可 ...
- 洛谷P1435 回文字串
题目背景 IOI2000第一题 题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “A ...
- 洛谷 P1435 回文字串
题目传送门 解题思路: 就是求一个字符串的最长回文子序列的长度,然后用整个的长度减去最长回文子序列的长度 AC代码: #include<iostream> #include<cstd ...
- P1435 回文字串(DP)
题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 "Ab3bd"插 ...
- 求字符串的最长回文字串 O(n)
昨天参加了某公司的校园招聘的笔试题,做得惨不忍睹,其中就有这么一道算法设计题:求一个字符串的最长回文字串.我在ACM校队选拔赛上遇到过这道题,当时用的后缀数组AC的,但是模板忘了没写出代码来. 回头我 ...
- hihocoder 第一周 最长回文字串
题目1 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程 ...
- POJ 3974 最长回文字串(manacher算法)
题意:给出一个字符串,求出最长回文字串. 思路:一开始我直接上了后缀数组DC3的解法,然后MLE了.看了DISCUSS发现还有一种计算回文字串更加优越的算法,就是manacher算法.就去学习了一下, ...
- 2238"回文字串"报告
题目描述: 回文串,就是从前往后和从后往前看都是一样的字符串.那么现在给你一个字符串,请你找出该字符串中,长度最大的一个回文子串. 输入描述: 有且仅有一个仅包含小写字母的字符串,保证其长度不超过50 ...
随机推荐
- mysql性能查看 命中率 慢查询
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...
- flask中的目录解析
首先我们看一下博客blog的封面,flask和django都属于web框架.不过flask属于轻量级web框架,功能的实现是通过扩展实现的,extension.py 中存放各个对象,具体的功能通过对象 ...
- MySql中4种批量更新的方法update table2,table1,批量更新用insert into ...on duplicate key update, 慎用replace into.
mysql 批量更新记录 MySql中4种批量更新的方法最近在完成MySql项目集成的情况下,需要增加批量更新的功能,根据网上的资料整理了一下,很好用,都测试过,可以直接使用. mysql 批量更新共 ...
- jQuery选择器我犯的错误(原创)
jQuery的选择器十分强大,但是在使用jQuery选择器的时候一定要十分小心,空格.冒号.引号到处都是坑,老手也不能避免,只能勤加练习,熟能生巧,掌握规律,为了练习,凡是到选择器的地方我都自己先敲, ...
- [已解决]报错: No module named pip
cmd中敲命令: python -m ensurepip 更新升级pip命令: python -m pip install --upgrade pip
- Sqlplus常用指令
一.ORACLE的启动和关闭1.在单机环境下2.在双机环境下二.Oracle数据库有哪几种启动方式1.startup nomount 非安装启动,这种方式启动下可执行:重建控制文件.重建数据库2.st ...
- flask获取参数
<!DOCTYPE html> body, html { width: 100%; height: 100%; } , ::after, ::before { -webkit-box-si ...
- Permission denied
记录在一次启动tomcat时提示:Permission denied 信息. 解释一下Permission denied的意思-没有权限 解决办法: sudo chmod -R 777 某一目录其中- ...
- SpringData 完全入门指南
SpringData 笔记 1. 配置项目 1.pom.xml <?xml version="1.0" encoding="UTF-8"?> < ...
- python爬虫爬取ip记录网站信息并存入数据库
import requests import re import pymysql #10页 仔细观察路由 db = pymysql.connect("localhost",&quo ...