洛谷P1435 回文子串
题目背景
IOI2000第一题
题目描述
回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。
比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。
注:此问题区分大小写
输入格式
一个字符串(0<strlen<=1000)
输出格式
有且只有一个整数,即最少插入字符数
输入输出样例
输入: 输出:
Ab3bd
下面是这道题的题解:
这道题我一共有两种解法,下面我会把这两种解法都分享给大家:
第一种解法
第一种解法是用dp来解:
解题思路:这道题可以看做是一道求最长公共子序列的一道题(经典dp问题)!
为什么这么说呢,首先,回文串的特性就是正着读反着读都一样,一组对称的字符串。所以我们把这个字符串倒序放置也是和原来一样的。
这仿佛就找到了一个突破口。
正序与倒序“公共”的部分就是我们回文的部分,如果把正序与倒序公共的部分减去你就会惊奇的发现剩余的字符就是你所要添加的字符,也就是所求的正解!
找到解题思路后我们就可以开始写了,最长公共自序列问题是个经典的dp问题,
最容易想到的方法就是开个二维数组dp[i][j],i,j分别代表两种状态;
那么我们的动态转移方程应该就是if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
依此即可解出最长公共自序列,用字符串长度减去即是正解
由于我比较懒,下面有不直接粘贴代码了。
如果你想要更优的解法,就可以把二维数组变一维,不过这里就不说了(a了就行了,哪里呢么多事)
第二种解法
一样是dp。。。。。。
不过这次利用的是区间dp。
区间dp就很好理解了。
不解释原因了,直接上思路:
状态:dp[i][j]从i到j区间内最长回文子序列长度。
转移方程:dp[i][j]=dp[i+1][j-1]+2 i和k能配对
max(dp[i+1][j],dp[i][j-1]) i和k不能配对
状态:dp[i][i]=1
答案:dp[1][n]
复杂度:O(n^2)
下面是是dp部分代码:
for(int len=;len<=n;len++)
{
for(int i=;i<=n-len+;i++)
{
int j=i+len-;
if(a[i]==a[j])
dp[i][j]=dp[i+][j-]+;
else
dp[i][j]=max(dp[i+][j],dp[i][j-]);
}
}
输入问题注意从a[1]开始输入
输出要用总长度-回文长度
下面是全部代码(区间dp)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define inf 100000000
//状态:dp[i][j]从i到j区间内最长回文子序列长度。
//转移方程:dp[i][j]=dp[i+1][j-1]+2 i和k能配对
// max(dp[i+1][j],dp[i][j-1]) i和k不能配对
//状态:dp[i][i]=1
//答案:dp[1][n]
//复杂度:O(n^2)
char a[];
int dp[][];
using namespace std;
int main()
{
scanf("%s",a+);
int n=strlen(a+);
for(int i=;i<=n;i++)
{
dp[i][i]=;
}
for(int len=;len<=n;len++)
{
for(int i=;i<=n-len+;i++)
{
int j=i+len-;
if(a[i]==a[j])
dp[i][j]=dp[i+][j-]+;
else
dp[i][j]=max(dp[i+][j],dp[i][j-]);
}
}
cout<<n-dp[][n];
return ;//不写return 0,考试就爆零
}
最后祝大家AC所有题!
给个赞再走呗?
洛谷P1435 回文子串的更多相关文章
- 洛谷 P1217 回文质数
洛谷 P1217 回文质数 链接 https://www.luogu.org/problem/P1217 题目 题目描述 因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 ...
- 洛谷P1217回文质数-Prime Palindrome回溯
P1217 [USACO1.5]回文质数 Prime Palindromes 题意:给定一个区间,输出其中的回文质数: 学习了洛谷大佬的回溯写法,感觉自己写回溯的能力不是很强: #include &l ...
- 洛谷 P1015 回文数 Label:续命模拟QAQ
题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数 ...
- 洛谷 P1015 回文数
#include<iostream> #include<cstdio> #include<cmath> #include<string> #includ ...
- 洛谷P1435 回文字串(dp)
题意 题目链接 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “Ab3bd”插入2个字符后可 ...
- 洛谷P1435 回文字串
题目背景 IOI2000第一题 题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “A ...
- 洛谷 - P1217 - 回文质数 - 枚举
https://www.luogu.org/problemnew/show/P1217 考虑暴力生成所有的回文数然后再判断是不是质数.注意个位的选择实际上只有4种.所以是 $4*10^3*10^3=4 ...
- 洛谷 P2010 回文日期
Noip2016普及组T2 题目描述 在日常生活中,通过年.月.日这三个要素可以表示出一个唯一确定的日期. 牛牛习惯用8位数字表示一个日期,其中,前4位代表年份,接下来2位代表月 份,最后2位代表日期 ...
- 洛谷 P2010 回文日期 题解
P2010 回文日期 题目描述 在日常生活中,通过年.月.日这三个要素可以表示出一个唯一确定的日期. 牛牛习惯用88位数字表示一个日期,其中,前44位代表年份,接下来22位代表月 份,最后22位代表日 ...
随机推荐
- CSS - input 美化
input{ padding: 20px; width: 100%; height: 5vh; margin-bottom: 2vh; border-radius: 10vw; border: 0; ...
- eclipse的重要快捷键
1.快速修正:ctrl + 1 2.单词补全:alt + / 3.查看轮廓:ctrl + o 4.打开eclipse中工作区的资源: ctrl + shift + r 它可以打开当前eclipse的工 ...
- C++编程学习(一) 概述
从一年前开通博客,陆陆续续写了一些总结类的东西,但是一直没push到网上.现在发现,分享自己的笔记也是自身学习.与他人交流的好方式.从今天开始,我会经常的push一些学习笔记到博客中,先从C++开始吧 ...
- java String字符串判断
判断空字符串:StringUtils.isBlank StringUtils.isBlank(null) = true StringUtils.isBlank("") = true ...
- 下载jQuery
下载jQuery :https://jquery.com/download/ . 将下载好的文件放到项目中 引入到代码中 <script type="text/javascript&q ...
- Vue.js(20)之 封装字母表(是这个名字吗0.0)
HTML结构: <template> <div class="alphabet-container"> <h1>alphabet 组件</ ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 常量
常量是固定值,在程序执行期间不会改变.这些固定的值,又叫做字面量. 常量可以是任何的基本数据类型,可分为整型数字.浮点数字.字符.字符串和布尔值. 常量就像是常规的变量,只不过常量的值在定义后不能进行 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 变量类型
变量其实只不过是程序可操作的存储区的名称.C++ 中每个变量都有指定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上. 变量的名称可以由字母.数字和下划线字 ...
- django数据库读写分离
django数据库读写分离 1. 配置数据库 settings.py文件中 用SQLite: DATABASES = { 'default': { 'ENGINE': 'django.db.backe ...
- LeetCode做题笔记之动态规划
LeetCode之动态规划 时间有限只做了下面这几道:70.338.877.96.120.95.647,后续会继续更新 70:爬楼梯 先来道简单的练练手,一道经典的动态规划题目 可以采用动态规划的备忘 ...