hdu 1513 1159 poj Palindrome (dp, 滚动数组, LCS)

news/2024/7/24 3:59:39

题目

以前做过的一道题, 今天又加了一种方法 整理了一下。。。。。

题意:给出一个字符串,问要将这个字符串变成回文串要添加最少几个字符。

 

方法一:

将该字符串与其反转求一次LCS,然后所求就是n减去 最长公共子串的长度。

额,,这个思路还是不是很好想。

LCS:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn = 5000+10;
 6 char s1[maxn], s2[maxn];
 7 int d[2][maxn], n;
 8 int mmin(int a,int b)
 9 {
10     return a>b?b:a;
11 }
12 int mmax(int a, int b)
13 {
14     return a<b?b:a;
15 }
16 void Lcs()
17 {
18     int i, j;
19     for(i = 1; i <= n; i++)
20         for(j = 1; j <= n; j++)
21             if(s1[i] == s2[j])
22                 d[i%2][j] = d[(i-1)%2][j-1] + 1;
23             else
24                 d[i%2][j] = mmax(d[(i-1)%2][j], d[(i%2)][j-1]);
25 }
26 int main()
27 {
28     int i;
29     while(cin>>n)
30     {
31         memset(d, 0, sizeof(d));
32         for(i=1; i<=n; i++)
33             cin>>s1[i];
34         for(i = n; i >=1; i--)
35             s2[i] = s1[n-i+1];
36         Lcs();
37         cout<<n-d[n%2][n]<<endl;
38     }
39     return 0;
40 }

 

方法二:

这个是discuss里的方法。

设ch[1]..ch[n]表示字符串1至n位,i为左游标,j为右游标 ,则i从n递减,j从i开始递增。
min[i][j]表示i和j之间至少需要插入多少个字符才能对称,初始置全0 ,我们最终需要得到的值是min[1][n].
则
if(ch[i]==ch[j])                                    //如果两个游标所指字符相同,向中间缩小范围
    min[i][j]=min[i+1][j-1];
else
     min[i][j] = 1 +  (min[i+1][j]和min[i][j-1]中的较小值);     //如果不同,典型的状态转换方程

 下面这个代码 是用的short int d[5000][5000]

在poj 可以水过,但是在hdu还超内存,,所有需要用滚动数组来 节省内存。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 int mmin(int a,int b)
 7 {
 8     return a>b?b:a;
 9 }
10 short int d[5010][5010];
11 int main()
12 {
13     int n,i,j;
14     char s[5010];
15     memset(d,0,sizeof(d));
16     cin>>n;
17     for(i=1; i<=n; i++)
18     cin>>s[i];
19     for(i=n; i>=1; i--)
20     for(j=i+1; j<=n; j++)
21     if(s[i]==s[j])
22     d[i][j]=d[i+1][j-1];
23     else
24     d[i][j]=mmin(d[i+1][j],d[i][j-1])+1;
25 
26     cout<<d[1][n]<<endl;
27     return 0;
28 }

 

因为d[i][j] 算的时候只是与 d[i+1][j] 和 d[i][j+1]有关,所有可以开一个d[2][5000]的数组。

滚动数组节省内存:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 int mmin(int a,int b)
 7 {
 8     return a>b?b:a;
 9 }
10 int d[2][5010];
11 int main()
12 {
13     int n,i,j;
14     char s[5010];
15     while(cin>>n)
16     {
17         memset(d, 0, sizeof(d));
18         for(i=1; i<=n; i++)
19             cin>>s[i];
20 
21         for(i=n; i>=1; i--)
22             for(j=i+1; j<=n; j++)
23                 if(s[i]==s[j])
24                     d[i%2][j]=d[(i+1)%2][j-1];
25                 else
26                     d[i%2][j]=mmin(d[(i+1)%2][j],d[i%2][j-1])+1;
27 
28         cout<<d[1][n]<<endl;
29     }
30     return 0;
31 }

 

贴一下别人博客里的滚动数组的介绍:

 

滚动数组 举个简单的例子:
int i,d[100];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i]=d[i-1]+d[i-2];
printf("%d",d[99]);
上面这个循环d[i]只需要解集中的前2个解d[i-1]和d[i-2];
为了节约空间用滚动数组的方法


int d[3];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i%3]=d[(i-1)%3]+d[(i-2)%3];
printf("%d",d[99%3]);


注意上面的运算,我们只留了最近的3个解,数组好象在“滚动?一样,所以叫滚动数组


对于二维数组也可以用这种方法 例如:
int i,j,d[100][100];
for(i=1;i<100;i++)
    for(j=0;j<100;j++)
        d[i][j]=d[i-1][j]+d[i][j-1];


上?的d[i][j]忪便赖于d[i-1][j],d[i][j-1];
迿用滚动数组
int i,,j,d[2][100];
for(i=1;i<100;i++)
    for(j=0;j<100;j++)
        d[i%2][j]=d[(i-1)%2][j]+d[i%2][j-1];


滚动数组实际是一种节约空间的办法,时间上没什么优势,多用于DP中,举个例子先: 
一个DP,平常如果需要1000×1000的空间,其实根据DP的特点,能以2×1000的空间解决问题,并且通过滚动,获得和1000×1000一样的效果。

转载于:https://www.cnblogs.com/bfshm/p/3671875.html


http://www.niftyadmin.cn/n/1026754.html

相关文章

【ULINK2仿真器stm32编程下载器】---- keil无法识别问题

之前由于JLINK仿真器有点问题&#xff0c;换了一个ULINK2仿真器&#xff1a;图片来源http://www.elecfans.com/d/1094778.html 使用的JTAG连接器是调试ARM 的标准&#xff08;2.54mm/0.1"&#xff09;20-针连接器&#xff0c;由于自己的板子接了一个外设&#xff0c;板子…

SQL Server 2008中的hierarchyid

这也是SQL Server 2008的一个重要新增特性。主要解决的问题是拥有层次关系的表格。例如我们日常生活中用到最多的组织结构图。我们一般会用一个Employees表保存员工数据&#xff0c;而每个员工则又可能会有相应的上级。以前要得到某个员工的所有上级&#xff0c;或者所有下级&a…

【Linux(bash)】中容易被忽略但又超好用的命令【持续更新】

Linux(bash)中容易被忽略但又超好用的命令【持续更新】 目录Linux(bash)中容易被忽略但又超好用的命令【持续更新】1 常用2 文件更新自动显示3 纯文本文件的多窗口功能4 按文件大小排序列出5 打包时排除掉某些文件6 借助alias,bash变量完成快捷操作6.1 使用alias设置命令别名6.…

基于CentOS7+Nginx+Daphne+uWSGI+Django3.2+supervisor+mysql8的单体架构服务器生产环境部署(二)

CentOS7NginxDaphneuWSGIDjango3.2supervisormysql8的服务器生产环境部署&#xff08;二&#xff09; 第一篇&#xff1a;基于CentOS7NginxDaphneuWSGIDjango3.2supervisormysql8的服务器生产环境部署&#xff08;一&#xff09;已经完成了基本使用http连接请求处理的部署&…

【Matlab】不是二进制 MAT 文件。请尝试执行 load -ASCII 以便以文本形式读取。

今天在用matlab打开matlab’s v7.3 mat file的时候&#xff0c;遇到了这个问题&#xff1a; 【Matlab】不是二进制 MAT 文件。请尝试执行 load -ASCII 以便以文本形式读取。 重新打开matlab 或者 更换mat存放的目录即可打开。 另外还可以用python打开&#xff0c;使用hdf5stora…

【Linux】将占据屏幕正常输出的服务移至后台

ALTF1234567切换终端 &#xff08;可能会被ulimit和limit.conf限制连接数&#xff0c;此时应该采取别的方式&#xff09; 无法脱机执行任务&#xff08;连接断了任务就终止&#xff09;使用screen 可以脱机执行任务数据流重定向supervisor 可以脱机执行任务& 、 [crtl]z 、…

【Linux】中root就是万能的吗?

不是 例子&#xff1a; bash只能管理自己的任务而不能管理其他bash的任务&#xff0c;所以即使是root也不能够将别人bash下面的任务拿来执行。

【Linux(vim)】下编辑却显示readonly的解决方法 E325: ATTENTION E45: ‘readonly‘ option is set (add ! to override)

自查一下是不是按了[crtl]z导致vim窗口关闭&#xff0c;当再次打开时出现了这个错误。 如果是这样导致出现的错误&#xff0c;应当意识到开启vim之后[crtl]z实际上把vim暂停并扔到了后台&#xff08;任务管理的命令&#xff09;。此时可以使用 jobs -l查看后台状态&#xff0c…