添加最少字符数构成使字符串构成回文
来源:互联网 发布:监控网络键盘 编辑:程序博客网 时间:2024/05/21 07:02
FROM:
http://www.cnblogs.com/zhengyuhong/p/3641418.html
Description
A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome.
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
Input
Your program is to read from standard input. The first line contains one integer: the length of the input string N, 3 <= N <= 5000. The second line contains one string with length N. The string is formed from uppercase letters from 'A' to 'Z', lowercase letters from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct.
Output
Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.
Sample Input
5Ab3bd
Sample Output
2
Source
IOI 2000
我看到这个题目第一时间是用递归算法直接做的,就几行代码,很简单的,但是提交,咦,超时哦,看来递归有很多重复工作,于是就想到用动态规划算法来解决这个问题。
算法如下:
记字符串为str,left为当前字符串最左边字符的索引下标,right则是当前字符串最右边字符的索引下标
1、如果字符串只有一个字符,返回0
2、如果字符串有两个字符,相同则返回0,否则返回1
3、字符串三个或者三个以上则有如下状态转移方程
1)、str[left] == str[right];则minAdd(str,left,right) = minAdd(str,left+1,right-1)
2)、str[left] != str[right];则minAdd(str,left,right) =1+ min( minAdd(str,left,right-1),minAdd(str,left+1,right) );
用m[][]记录left~right字符串构成回文所需的最少字符数,可以避免重复计算。
具体可以在代码中看到m[][]的初始化与构造。
#include <iostream>using namespace std;const short N = 5001;short m[N][N];short foo(char* str,short left,short right){ if(left == right) { return m[left][right] = 0; } else if( left + 1 == right ) { if( str[left] == str[right] ) { return m[left][right] = 0; } else { return m[left][right] = 1; } } else { if( m[left][right] != -1 ) { return m[left][right]; } else { if(str[left] == str[right]) { return m[left][right] = foo(str,left + 1, right - 1); } else { short a = foo(str,left, right - 1) + 1; short b = foo(str,left + 1, right) + 1; return m[left][right] = a < b ? a : b; } } }}int main(int argc, char** argv) { char str[N]; short i, j, n; for( i = 0; i < N; ++i) { for(j =0; j < N; ++j) { m[i][j] = -1; } } cin>>n; i = 0; while(i < n) { cin>>str[i++]; } str[i]=0; cout<<foo(str,0,n - 1); return 0;}
本来二维数组m[N][N]是int型的,但是OJ报告内存超过限制,转用short即可,可以覆盖5000,因为题目要求是 2<N<5001,或者可以使用滚动数组,可以看如下的另一个代码。
#include <iostream>#include <cstring>using namespace std;const int N = 5001;short m[2][N];short foo(char* str, short n){ short i, j, k, k1, k2, a, b; for(k = 1; k < n; ++k) { k1 = k & 1; k2 = (k - 1) & 1; for(i = 0; i + k < n; ++i) { j = i + k; if(str[i] == str[j]) { m[k1][i] = m[k1][i+1]; } else { m[k1][i] = 1 + (m[k2][i] < m[k2][i+1] ? m[k2][i] : m[k2][i+1]); } } } return m[(n-1)&1][0];}int main(int argc, char** argv) { char str[N]; short i, n; i = 0; cin>>n; while(i < n) { cin>>str[i++]; } str[i]=0; cout<<foo(str,n); return 0;}
在这里用到一个滚动数组,妙用了&1,就是轮换使用两个一维数组,降低了一个数量级的空间复杂度。
写一次代码就有些心得体会,看来算法还是得通过实现来巩固掌握。
0 0
- 添加最少字符数构成使字符串构成回文
- dp问题 添加最少的字符构成回文串
- poj1159 Palindrome dp 加最少字符构成回文
- 构成回文序列最少要增加多少字符
- 构成回文序列最少要增加多少字符
- POJ 1159 最少添加几个字母构成回文 DP
- 添加最少字符使成为回文字符串
- POJ1159 Palindrome(dp加最少字母构成回文字符串)
- 添加最少的字符使整体字符串都是回文字符串
- UVA11548 DP计算添加多少元素可以构成回文字符串
- 添加最少的字符使字符串成为回文
- 最少插入几个字符可构成回文串(动归+滚动数组)
- 409. Longest Palindrome (计算可由一个字符串中数字字符构成的最长回文数的长度)
- 构成最小回文数的分析
- 字符串问题---添加最少字符使字符串整体都是回文字符串
- 【编程题】-C++实现:判断字符串在末尾加一个字符,能否构成回文串
- [腾讯笔试]求一个字符串删除若干字符可构成一个回文串
- 构成回文序列至少要删掉多少字符
- Unix GREP的用法
- 一些问题
- Oracle数据库的管理
- 婆媳关系之————我与婆婆的那些事!
- OSI网络七层模型和TCP/IP协议模型
- 添加最少字符数构成使字符串构成回文
- Mac shell 文件批量替换字符串
- [日语学习] コスパ
- Win7下安装CentOS 6.5双系统
- windows 服务的注册与缷载
- Jboss无法通过IP地址访问,只能用localhost\127.0.0.1访问
- MyEclipse6.5中运行Tomcat7
- cublas矩阵乘
- 公有云与私有云优劣势调研