poj 1159 Palindrome
2011-06-18 18:06
423 查看
/* Name: poj 1159 Palindrome Author: Unimen Date: 16/05/2011 18:55 Description: 最长公共子序列的变形 */ /* 解题报告: 参照李鑫ppt: 1、对于一个串S=a1a2…an,求最小的m,使得存在一个串S’=b1b2…bm+n满足S为S’的一个子串(可不连续),并且bi=bm+n-i+1(i=1…m+n)。 2、设S ’各个字符中不为S中字符的字符位置集为X 。故 i 属于X 或 m+n-i+1属于X 是不可能同时成立的。所以可以把S中的字符分成两类A,B: A:S’中与此字符对称的字符出现在S’-S中 B:S’中与此字符对称的字符出现在S中 3、比如把Ab3bd扩充成 d A b 3 b A d(红色的字母是添加的) 1 2 3 4 5 6 7 位置2,7的对称位置的字符不属于S, 故A={2, 7} 位置3,4,5的对称位置的字符属于S, 故B={3, 4, 5} 4、有以下结论: |A|+|B|=|S|=n |A|=|X| B是回文词且B是S的子串 |X|=|A|=n-|B|,问题转化为求S的最大回文子串B。 注: 一、由于此题数据量较大因此如果dp数组开成int dp[50001][50001]内存会超出限制 解决方法有两个: 1、改为short,尤其是比赛的时候如果没有好的办法,可以优先考虑这种方法 2、用滚动数组存储。滚动数组在做DP的题时经常用到,需注意。下面的代码是用滚动数组做的 二、求回文的时候可以用最长公共子序列解决 */ #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; short dp[2][5001]; //滚动数组 char szLine[5001]; int n; int main() { int i, j; while(cin>>n) { scanf("%s", szLine+1); memset(dp, 0, sizeof(dp)); for(i=1; i<=n; ++i) { for(j=1; j<=n; ++j) { if(szLine[i] == szLine[n-j+1]) { dp[i%2][j] = dp[(i-1)%2][j-1] + 1; } else { dp[i%2][j] = _cpp_max(dp[(i-1)%2][j], dp[i%2][j-1]); //提交时_cpp_max应改为max } } } cout<<n-dp[n%2] <<endl; } return 0; }
相关文章推荐
- POJ 1159--Palindrome(回文序列)
- 【转】POJ 1159 Palindrome【经典的DP回文问题】
- poj1159--Palindrome(dp:最长公共子序列变形 + 滚动数组)
- poj&nbsp;1159&nbsp;Palindrome(DP)
- Poj 1159 Palindrome
- poj 1159 Palindrome --- LCS减内存
- POJ 1159 Palindrome(区间dp)
- POJ1159 Palindrome (动态规划)
- poj 1159 Palindrome(最长公共子序列 + 滚动数组)
- POJ 1159 Palindrome (LCS)
- POJ 1159 Palindrome
- poj 1159 Palindrome(dp)
- poj-1159-Palindrome
- 【转】POJ 1159 Palindrome【经典的DP回文问题】
- POJ 1159 Palindrome 最大公共子序列+滚动数组
- POJ-1159-Palindrome -dp
- POJ1159 Palindrome
- POJ1159 Palindrome
- poj 1159 Palindrome - 动态规划
- POJ 1159:Palindrome 最长公共子序列