POJ 1159 Palindrome(滚动数组)

链接:click here

题意:

给你一串字符串,让你求最少加入几个字符,才能使得这个字符串是个回文串。

思路:

设a[i]是这个字符串,b[i]是这个字符串的逆序串。那么a[i],b[i]的最长公共子序列就是所求的字符串里拥有的最大的回文串。然后用总串长减去最大的回文串长度即为所求。求最长公共子序列的公式为:dp[i][j]=max(dp[i-1] [j],dp[i][j-1])if(a[i]==b[i])dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);

如果直接求的话,会超时。

用两种解决方法:

1,shor int数组

2,运用动态数组。

根据dp滚动的过程我们可以知道,dp[]i][j]的值不会与dp[i-2][0.....n]的值有关系。

那么可以把dp[i][j]的值覆盖到dp[i-2][j]上。即dp[i][j]为dp[i%2][j];

代码:

<span style="font-size:12px;">#include <iostream>
#include <stdio.h>
#include <string.h>
#define  max(a,b) (a>b?a:b)
using namespace std;
const int maxn=5005;
const int inf = 0x3f3f3f3f;
short int dp[maxn][maxn];
int a[maxn],b[maxn];
int n,m,i,j,length;
inline int input()
{
    int res=0,f=1,c;
    while(!isdigit(c = getchar()) && c!='-');
    c=='-' ? f=0 : res=c-'0';
    while(isdigit(c = getchar()))
        res = res*10 + c-'0';
    return f ? res : -res;
}
int main()
{
    char str;
    //n=input();       //POJ 竟然不支持快速输入,写成这样返回WA
    scanf("%d",&n);
    getchar();
    for(i=1; i<=n; i++)
    {
        scanf("%c",&str);
        a[i]=str;
        b[n-i+1]=str;
    }
    for(i=0; i<=n; i++)
    {
        dp[i][0]=0;
        dp[0][i]=0;
    }
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=n; j++)
        {
            dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
            if(a[i]==b[j])
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);   //关键
            }
        }
    }
    length=dp[n][n];
    printf("%d\n",n-length);                            //总长减去回文子长即为所求
    return 0;
}
</span>

滚动数组:

<span style="font-size:12px;">#include <iostream>
#include <stdio.h>
#include <string.h>
#define  max(a,b) (a>b?a:b)
using namespace std;
const int maxn=5005;
const int inf = 0x3f3f3f3f;
short int dp[maxn][maxn];
int a[maxn],b[maxn];
int n,m,i,j,length;
inline int input()
{
    int res=0,f=1,c;
    while(!isdigit(c = getchar()) && c!='-');
    c=='-' ? f=0 : res=c-'0';
    while(isdigit(c = getchar()))
        res = res*10 + c-'0';
    return f ? res : -res;
}
int main()
{
    char str;
    //n=input();
    scanf("%d",&n);
    getchar();
    for(i=1; i<=n; i++)
    {
        scanf("%c",&str);
        a[i]=str;
        b[n-i+1]=str;
    }
    dp[1][0]=dp[0][0]=0;
    for(i=0; i<=n; i++)
    {
        //dp[i][0]=0;
        dp[0][i]=0;
    }
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=n; j++)
        {
            dp[i%2][j]=max(dp[i%2][j-1],dp[(i-1)%2][j]);
            if(a[i]==b[j])
            {
                dp[i%2][j]=max(dp[i%23][j],dp[(i-1)%2][j-1]+1);
            }
        }
    }
    length=dp[n%2][n];
    printf("%d\n",n-length);
    return 0;
}
</span>
时间: 2024-11-03 03:25:03

POJ 1159 Palindrome(滚动数组)的相关文章

LCS(滚动数组) POJ 1159 Palindrome

题目传送门 1 /* 2 LCS裸题:长度减去最大相同长度就是要插入的个数 3 dp数组二维都开5000的话就会超内存,这里就用到了滚动数组, 4 因为在LCS的计算中,i的变化只相差1,所以可以通过对2取余来进行滚动:) 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <cstring> 9 #include <algorithm> 10 #include <string> 1

poj 1159 Palindrome lcs+滚动数组

点击打开链接题目链接 Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 52910   Accepted: 18248 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

POJ 1159 Palindrome(lcs加滚动数组)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 52350   Accepted: 18041 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

POJ 1159 Palindrome &amp;&amp; HDU 1159 Common Subsequence

1.先说说杭电的1159吧! 这道题是基础动规,比较简单! 就是要你求最长的公共子序列(不要优化) 动态转移方程: dp[i+1][j+1]=(a[i]=b[i])?dp[i][j]+1:max(dp[i+1][j],dp[i][j+1]) AC代码: #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 520 char a[N],b[N]; in

poj 1159 Palindrome (LCS)

链接:poj 1159 题意:给定一个字符串,求最少添加多少个字符可使得该字符串变为回文字符串 分析:设原序列S的逆序列为S' ,最少需要补充的字母数 = 原序列S的长度 - S和S'的最长公共子串长度 原因:要求最少添加几个字符,我们可以先从原串中找到一个最长回文串,然后对于原串中不属于这个回文串的字符,在它关于回文串中心的对称位置添加一个相同字符即可.那么需要添加的字符数量即为n-最长回文串长度. 最长回文串可以看作是原串中前面和后面字符的一种匹配(每个后面的字符在前面找到一个符合位置要求的

POJ 1159 Palindrome 题解

本题的题意理解之后,就是求最长回文子序列 longest palindrome subsequence,这里注意子序列和子串的区别. 有两种求法,一种是直接求,相当于填矩阵右上对角阵,另一种是转化为longest common subsequence的求法. 最大难点就是要求内存不能使用二维的. 故此第一种方法是有点难度的,因为需要把二维矩阵的对角线转化为一维表记录,对好下标就好了. 第二中方法会稍微容易点,效率都是一样的O(n*n). 方法1: #include <cstdio> const

POJ 1159 Palindrome

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 51518   Accepted: 17733 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

LCS POJ 1159 Palindrome

题目传送门 1 /* 2 LCS裸题:长度减去最大相同长度就是要插入的个数 3 */ 4 #include <cstdio> 5 #include <iostream> 6 #include <cstring> 7 #include <algorithm> 8 #include <string> 9 using namespace std; 10 11 const int MAXN = 5e3 + 10; 12 const int INF = 0

POJ 1159 Palindrome DP

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 51913   Accepted: 17877 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