P1435 回文字串

题目背景

IOI2000第一题

题目描述

回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。

比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。

注:此问题区分大小写

输入输出格式

输入格式:

一个字符串(0<strlen<=1000)

输出格式:

有且只有一个整数,即最少插入字符数

输入输出样例

输入样例#1:

Ab3bd
输出样例#1:

2
 
分析:
1、模型就是“公共子序列”的变式
2、模型要确保建对,毕竟知道公共子序列的变式之后还有细节要注意
3、用滚动数组优化空间
 
 

分析:

洛谷题解,讲的相当详细

解题思路:该题说是考察如何将一个字符串添加成一个回文串的,不如说是一道求最长公共自序列的变式题,为啥这么说呢?肯定是有原因在里面的

  1. 首先,我们要摸清回文串的特性,回文就是正着读反着读一样,一种非常对称不会逼死强迫症的字符串;这就是我们的突破口。。。你难道以为是逼死强迫症么?哈哈,太天真了,突破口其实是因为回文正着读反着读都相同的特性。。。这样我们就可以再建一个字符数组存储倒序的字符串

  2. 我们先分析下样例:ab3bd,

它的倒序是:db3ba

这样我们就可以把问题转化成了求最长公共自序列的问题,为啥可以这么转化呢?

它可以这么理解,正序与倒序“公共”的部分就是我们回文的部分,如果把正序与倒序公共的部分减去你就会惊奇的发现剩余的字符就是你所要添加的字符,也就是所求的正解

ad da把不回文的加起来就是我们梦寐以求的东西:回文串(卧槽?太没追求了)

把ad,da加起来成回文串就是adb3bda,所以这个问题就可以转化成了求最长公共自序列的问题,将字符串的长度减去它本身的“回文的”(最长公共自序列)字符便是正解

  1. 找到解题思路后我们就可以开始写了,最长公共自序列问题是个经典的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 回文字串的更多相关文章

  1. P1435 回文字串(LCS问题)

    题目背景 IOI2000第一题 题目描述(题目链接:https://www.luogu.org/problem/P1435) 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成 ...

  2. 洛谷P1435 回文字串(dp)

    题意 题目链接 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “Ab3bd”插入2个字符后可 ...

  3. 洛谷P1435 回文字串

    题目背景 IOI2000第一题 题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “A ...

  4. 洛谷 P1435 回文字串

    题目传送门 解题思路: 就是求一个字符串的最长回文子序列的长度,然后用整个的长度减去最长回文子序列的长度 AC代码: #include<iostream> #include<cstd ...

  5. P1435 回文字串(DP)

    题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 "Ab3bd"插 ...

  6. 求字符串的最长回文字串 O(n)

    昨天参加了某公司的校园招聘的笔试题,做得惨不忍睹,其中就有这么一道算法设计题:求一个字符串的最长回文字串.我在ACM校队选拔赛上遇到过这道题,当时用的后缀数组AC的,但是模板忘了没写出代码来. 回头我 ...

  7. hihocoder 第一周 最长回文字串

    题目1 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程 ...

  8. POJ 3974 最长回文字串(manacher算法)

    题意:给出一个字符串,求出最长回文字串. 思路:一开始我直接上了后缀数组DC3的解法,然后MLE了.看了DISCUSS发现还有一种计算回文字串更加优越的算法,就是manacher算法.就去学习了一下, ...

  9. 2238"回文字串"报告

    题目描述: 回文串,就是从前往后和从后往前看都是一样的字符串.那么现在给你一个字符串,请你找出该字符串中,长度最大的一个回文子串. 输入描述: 有且仅有一个仅包含小写字母的字符串,保证其长度不超过50 ...

随机推荐

  1. Some Simple Mistakes I had

    This week, I had some mistakes. It is really hard to say: #1 py business what's happening l = abs(px ...

  2. xcode Delete current line

    Delete a line like eclipse CTRL+D (tested on Xcode 4.5.1) : First of all, change these rights : sudo ...

  3. python基础-包和模块

    Python基础-包与模块 写在前面 如非特别说明,下文均基于Python3 摘要 为重用以及更好的维护代码,Python使用了模块与包:一个Python文件就是一个模块,包是组织模块的特殊目录(包含 ...

  4. https://www.cnblogs.com/limanjihe/p/10184327.html

    https://www.cnblogs.com/limanjihe/p/10184327.html https://blog.csdn.net/xnnswmzdszyd/article/details ...

  5. yum常见问题

    --> Finished Dependency Resolution Error: Multilib version problems found. This often means that ...

  6. 获取Windows某一目录下的所有文件名

    #include <sys/types.h> #include <dirent.h>     std::vector<std::string> get_all_fi ...

  7. mac 密码重置

    首先请开机或重新启动系统,在电脑刚启动时,请按下键盘上的 command+S 组合键不动, 接下来会在屏幕上看到一串串的命令字符显示,当进入安全模式以后,会看到 一个 root 开始的命令行输入端口. ...

  8. mongo import excle

    mongoimport --host 192.*******.** --db **  --collection **  --type csv --headerline --file /*****.cs ...

  9. USACO 2014 US Open Decorating The Pastures

    题目大意: 给定n个点m条边的无向图 判断这个图能否将所有点依次染色为F J F J 若能输出最多能染多少个J 若不能输出-1 就是给一个图01染色 过程中判断是否出现不符合的情况 即点1到点2到点3 ...

  10. React-Native 指定模拟器RUN-IOS

    react-native run-ios --simulator "iPhone 7”