字符串回文子序列问题
2015-11-05 20:25
267 查看
【问题1】求字符串回文子序列的个数
问题:
给定字符串,求它的回文子序列个数。回文子序列反转字符顺序后仍然与原序列相同。例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个。内容相同位置不同的子序列算不同的子序列。
分析与解法:
(注意:与子串不同,子序列可以是不连续的,只要元素的前后相对位置不变。)
解法一:递归
假设s[0 … n-1]是给定的序列,长度为让 c(0,n-1)表示序列s[0 … n-1] 的回文子序列的个数。
如果s的最后一个元素和第一个元素是相同的:c(1, n-1) + c(0, n-2) + 1。
如果s的最后一个元素和第一个元素是不同的,这时:c(0, n-1) = c(1, n-1) + c(0, n-2) - c(1, n-2) ,即”ab”+ “ba” - “b” 。
可以写出如下递归程序:
解法二:动态规划
解法一中存在重复计算的问题,且当字符串长度过大时,递归的时间复杂度会很高。可以采用动态规划的方法。
用dp[j][j+i]表示s[j…j+i]之间的回文子序列的个数,
如果s的最后一个元素和第一个元素是相同的:dp[j][j+i] = dp[j+1][j+i] + dp[j][j+i-1] + 1。
如果s的最后一个元素和第一个元素是不同的,这时:dp[j][j+i] = dp[j+1][j+i] + dp[j][j+i-1] - dp[j+1][j+i-1],即”ab”+ “ba” - “b”。
这里可以将二维数组dp的值列出,方便理解。其中橙色区域的数值只与黄色区域的数值有关,以dp[0][1]为例,若首尾元素相同,则等于dp[1][1] + dp[0][0] + 1;若首尾元素不同,则等于dp[1][1] + dp[0][0] - dp[1][0]。
【问题2】求字符串回文子序列的最大长度
http://www.acmerblog.com/longest-palindromic-subsequence-5721.html
问题:
给定字符串,求它的回文子序列个数。回文子序列反转字符顺序后仍然与原序列相同。例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个。内容相同位置不同的子序列算不同的子序列。
分析与解法:
(注意:与子串不同,子序列可以是不连续的,只要元素的前后相对位置不变。)
解法一:递归
假设s[0 … n-1]是给定的序列,长度为让 c(0,n-1)表示序列s[0 … n-1] 的回文子序列的个数。
如果s的最后一个元素和第一个元素是相同的:c(1, n-1) + c(0, n-2) + 1。
如果s的最后一个元素和第一个元素是不同的,这时:c(0, n-1) = c(1, n-1) + c(0, n-2) - c(1, n-2) ,即”ab”+ “ba” - “b” 。
可以写出如下递归程序:
int count(string str, int i, int j)//调用时count(str, 0, n-1); { if(i == j)//一个元素即是它本身 return 1; if(i > j)//只计算顺序时的子序列 return 0; if(str[i] != str[j])//若首尾不同 return count(str, i + 1, j) + count(str, i, j - 1) - count(str, i + 1, j - 1); else//若首尾相同 return count(str, i + 1, j) + count(str, i, j - 1) + 1; }
解法二:动态规划
解法一中存在重复计算的问题,且当字符串长度过大时,递归的时间复杂度会很高。可以采用动态规划的方法。
用dp[j][j+i]表示s[j…j+i]之间的回文子序列的个数,
如果s的最后一个元素和第一个元素是相同的:dp[j][j+i] = dp[j+1][j+i] + dp[j][j+i-1] + 1。
如果s的最后一个元素和第一个元素是不同的,这时:dp[j][j+i] = dp[j+1][j+i] + dp[j][j+i-1] - dp[j+1][j+i-1],即”ab”+ “ba” - “b”。
这里可以将二维数组dp的值列出,方便理解。其中橙色区域的数值只与黄色区域的数值有关,以dp[0][1]为例,若首尾元素相同,则等于dp[1][1] + dp[0][0] + 1;若首尾元素不同,则等于dp[1][1] + dp[0][0] - dp[1][0]。
int count(string str,int n) { int dp[MAXSIZE][MAXSIZE], tmp; memset(dp,0,sizeof(dp));//dp数组中所有元素置0 for(int i=0; i<n; i++) dp[i][i] = 1;//一个元素即是它本身 //i表示当前长度为i+1的子序列 for(int i=1; i<n; i++) { tmp = 0; //考虑所有连续的长度为i+1的子串. 该串为 str[j, j+i] for(int j=0; j+i<n; j++) { if(str[j] == str[j+i])//若首尾相同 tmp = dp[j+1][j+i] + dp[j][j+i-1] + 1; else//若首尾不同 tmp = dp[j+1][j+i] + dp[j][j+i-1] - dp[j+1][j+i-1]; dp[j][j+i] = tmp; } } //返回串 str[0][n-1] 的结果 return dp[0][n-1]; }
【问题2】求字符串回文子序列的最大长度
http://www.acmerblog.com/longest-palindromic-subsequence-5721.html
相关文章推荐
- 2015 11 03 内存分区
- [JPA错误]javax.persistence.EntityNotFoundException: Unable to find xxx
- 第9章 保护spring应用 9.1 Spring Security介绍
- Application, Activity, ContentProvider启动顺序
- synchronized详解
- [IOS]VMware上虚拟机MAC安装XCode
- Test01
- UVA - 11488 Hyper Prefix Sets(trie树)
- Mybatis与Ibatis比较
- jdk升级
- Linux下实现一个带时标的消息打印
- leetcode之House Robber(打家劫舍)
- C数据结构学习历程(3) 顺序栈之 一般表达式转化后缀式
- SQL Server 2008 表变量 临时表
- 为什么上传文件的表单需要设置enctype="multipart/form-data"
- [课堂实践与项目]IOS网络下载之 Post请求和Get请求
- 2015 11 01 结构体指针
- hdu5146
- Swift(十、类和结构体)
- java.lang.NoSuchMethodError: org.slf4j.impl.StaticLoggerBinder.getSingleton()Lorg/slf4j/impl/StaticL