(1513)HDU-lcs+滚动数组

本文详细阐述了一个算法问题,即通过最少的字符插入操作将普通字符串转化为回文串,并提供了动态规划(DPLCS)的解决方案。通过比较原字符串与其反转后的字符串之间的最长公共子序列(LCS),可以确定所需的最小插入次数。文章还讨论了滚动数组的应用以优化空间复杂度,以及无后效性的概念。通过实例和代码实现,展示了如何高效地解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Palindrome



Problem 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.
 

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
5 Ab3bd
 

Sample Output
2
呜呜还是不知道格式怎么搞····
那就在这里面写了
题意:问你再填几个字符形成回文字符串,最开始的我的想法是枚举,分奇数还是偶数n,可是发现枚举的不一定是最小的,如果你枚举一个位置,整体字符串就会发生变化,这道题的正解是DP LCS
做法:先把字符串翻过来,与原字符串求LCS 这样求出的值用n - dp[n][n]就是最小值了,如果不知道为什么,画画图就会发现。
注意:这里面dp数组正常时5000*5000,这样会MTL,我们应用了滚动数组。先贴个连接
http://blog.youkuaiyun.com/niushuai666/article/details/6677982
PS:小牛的博客还是拜读了好多的 :)
滚动数组的作用在于优化空间,主要应用在递推或动态规划中(如01背包问题)。因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N很大的情况下可以达到压缩存储的作用。
这里主要应用了无后效性,当前状态只与前一个或者前两个状态有关。
滚动数组实际是一种节省空间的办法,时间上没啥优势,多用于DP中,举个例子吧: 

一个DP,平常如果需要1000×1000的空间,其实根据DP的无后效性,可以开成2×1000,然后通过滚动,获得和1000×1000一样的效果。滚动数组常用于DP之中,在DP过程中,我们在由一个状态转向另一个状态时,很可能之前存储的某些状态信息就已经无用了,例如在01背包问题中,从理解角度讲我们应开DP[i][j]的二维数组,第一维我们存处理到第几个物品,也就是阶段了,第二维存储容量,但是我们获得DP[i],只需使用DP[i - 1]的信息,DP[i - k],k>1都成了无用空间,因此我们可以将数组开成一维就行,迭代更新数组中内容,滚动数组也是这个原理,目的也一样,不过这时候的问题常常是不可能缩成一维的了,比如一个DP[i][j]需要由DP[i - 1 ][k],DP[i - 2][k]决定,i<n,0<k<=10;n <= 100000000;显然缩不成一维,正常我们应该开一个DP[100000005][11]的数组,结果很明显,超内存,其实我们只要开DP[3][11]就够了DP[i%3][j]由DP[(i - 1)%3][k]和DP[(i - 2)%3][k]决定,空间复杂度差别巨大。

学习了·····

#include<iostream> #include<cstdio> #include<string.h> #include<string> #include<set> #include<algorithm> #include<cmath> #include<stdlib.h> #define ll __int64 #define MAX 1000009 using namespace std; int dp[2][5009]; int solve_dp(char* x,char* y,int n) {     int i,j;     int now,pre;     memset(dp,0,sizeof(dp));//³õʼ»¯     for(i = 1;i<=n;i++)     {         for(j = 1;j<=n;j++)         {             now = i%2;             pre = 1 - now ;             if(x[i-1]==y[j-1])                 dp[now][j] = dp[pre][j-1] + 1;             else                 dp[now][j] = max(dp[now][j-1],dp[pre][j]);         }     }     return dp[n%2][n]; } int main() {     char a[5009],b[5009];     int n;     while(~scanf("%d",&n))     {         scanf("%s",a);         strcpy(b,a);         strrev(a);         int ans = solve_dp(a,b,n);         printf("%d\n",n-ans);     }     return 0; }
                                                                                                                                                                                                                                                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值