题目

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

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

方法一:

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

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

LCS:

 #include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = +;
char s1[maxn], s2[maxn];
int d[][maxn], n;
int mmin(int a,int b)
{
return a>b?b:a;
}
int mmax(int a, int b)
{
return a<b?b:a;
}
void Lcs()
{
int i, j;
for(i = ; i <= n; i++)
for(j = ; j <= n; j++)
if(s1[i] == s2[j])
d[i%][j] = d[(i-)%][j-] + ;
else
d[i%][j] = mmax(d[(i-)%][j], d[(i%)][j-]);
}
int main()
{
int i;
while(cin>>n)
{
memset(d, , sizeof(d));
for(i=; i<=n; i++)
cin>>s1[i];
for(i = n; i >=; i--)
s2[i] = s1[n-i+];
Lcs();
cout<<n-d[n%][n]<<endl;
}
return ;
}

方法二:

这个是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还超内存,,所有需要用滚动数组来 节省内存。

 #include<iostream>
#include<cstring>
#include<cstdio>
using namespace std; int mmin(int a,int b)
{
return a>b?b:a;
}
short int d[][];
int main()
{
int n,i,j;
char s[];
memset(d,,sizeof(d));
cin>>n;
for(i=; i<=n; i++)
cin>>s[i];
for(i=n; i>=; i--)
for(j=i+; j<=n; j++)
if(s[i]==s[j])
d[i][j]=d[i+][j-];
else
d[i][j]=mmin(d[i+][j],d[i][j-])+; cout<<d[][n]<<endl;
return ;
}

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

滚动数组节省内存:

 #include<iostream>
#include<cstring>
#include<cstdio>
using namespace std; int mmin(int a,int b)
{
return a>b?b:a;
}
int d[][];
int main()
{
int n,i,j;
char s[];
while(cin>>n)
{
memset(d, , sizeof(d));
for(i=; i<=n; i++)
cin>>s[i]; for(i=n; i>=; i--)
for(j=i+; j<=n; j++)
if(s[i]==s[j])
d[i%][j]=d[(i+)%][j-];
else
d[i%][j]=mmin(d[(i+)%][j],d[i%][j-])+; cout<<d[][n]<<endl;
}
return ;
}

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

滚动数组 举个简单的例子:
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一样的效果。

hdu 1513 && 1159 poj Palindrome (dp, 滚动数组, LCS)的更多相关文章

  1. HDU 5617 Jam's maze dp+滚动数组

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5617 bc(中文):http://bestcoder.hdu.edu.cn/contest ...

  2. HDU - 4576 Robot(概率dp+滚动数组)

    题意:所有的格子围成一个圈,标号为1~n,若从格子1出发,每次指令告知行走的步数,但可能逆时针也可能顺时针走,概率都是1/2,那么问走了m次指令后位于格子l~r(1≤l≤r≤n)的概率. 分析: 1. ...

  3. hdu Max Sum Plus Plus(dp+滚动数组)

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1024 m为段,要深刻理解题意,并没有说是段与段要连接. 题解链接:http://blog.csdn.n ...

  4. HDU 1024 Max Sum Plus Plus --- dp+滚动数组

    HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值, ...

  5. HDU 5119 Happy Matt Friends (背包DP + 滚动数组)

    题目链接:HDU 5119 Problem Description Matt has N friends. They are playing a game together. Each of Matt ...

  6. POJ 3666 Making the Grade (DP滚动数组)

    题意:农夫约翰想修一条尽量平缓的路,路的每一段海拔是A[i],修理后是B[i],花费|A[i] – B[i]|,求最小花费.(数据有问题,代码只是单调递增的情况) #include <stdio ...

  7. USACO 2009 Open Grazing2 /// DP+滚动数组oj26223

    题目大意: 输入n,s:n头牛 s个栅栏 输入n头牛的初始位置 改变他们的位置,满足 1.第一头与最后一头的距离尽量大 2.相邻两头牛之间的距离尽量满足 d=(s-1)/(n-1),偏差不超过1 3. ...

  8. poj - 1159 - Palindrome(滚动数组dp)

    题意:一个长为N的字符串( 3 <= N <= 5000).问最少插入多少个字符使其变成回文串. 题目链接:http://poj.org/problem?id=1159 -->> ...

  9. hdu 1513(dp+滚动数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 思路:n这么大,可以采用滚动数组,然后就是求原串和反串的LCS了. #include<io ...

随机推荐

  1. SQL Server备份事务日志结尾(Tail)

    原文:http://blog.csdn.net/tjvictor/article/details/5256906   事务日志结尾经常提交数据库未备份的事务日志内容.基本上,每一次你执行事务日志备份时 ...

  2. java性能优化策略

    1. 尽量使用局部变量代替成员变量,循环中对成员变量.方法的调用不超过2次 2. ArrayList如果知道大小,初始化时应指明 3. HashMap的遍历,用Entry 4. 如果确定类不可继承尽量 ...

  3. 解决方法:java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index;

    hibernate4.3版本 报错: 把实体注解的声明方式修改一下解决,如: 将 @Entity@Table(name=”table_name”)改为@Entity(name=”table_name” ...

  4. 【POJ】【1741】/【BZOJ】【1468】Tree

    点分治 怎么又一道叫Tree的题目……真是醉了. 本题为漆子超论文<分治算法在树的路径问题中的应用>例一 题解 : http://blog.csdn.net/sdj222555/artic ...

  5. 【Unity--Apwork框架】AOP编程--拦截,用于缓存和异常处理(Unity框架的拦截注入-Interception)

    第一步:定义拦截行为:CachingBehavior 和 ExceptionLoggingBehavior 他们都继承接口:IInterceptionBehavior (程序集 Microsoft.P ...

  6. 《head first java 》读书笔记(三)

    Updated 2014/04/03 --P518 Thread需要任务,任务是实现过Runnable的实例.Runnalbe这个接口只有一个方法.run()会是新线程所执行的第一项方法.要把Runn ...

  7. Unity3D研究院之Machine动画脚本自动生成AnimatorController

    原地址: http://www.xuanyusong.com/archives/2811 以前的项目一直不敢用Machine动画,因为当时立项的时候Machine动画还不成熟,最近项目做得差不多了我能 ...

  8. unity3d旋转摄像机脚本

    void Update () { )) { if (axes == RotationAxes.MouseXAndY) { // Read the mouse input axis rotationX ...

  9. uniqueidentifier 数据类型(转)

     想要产生这种唯一标识的格式的数据: 6F9619FF-8B86-D011-B42D-00C04FC964FF 应该怎么做呢?答: uniqueidentifier 数据类型可存储 16 字节的二进制 ...

  10. POJ 3277 City Horizon(叶子节点为[a,a+1)的线段树+离散化)

    网上还有用unique函数和lowerbound函数离散的方法,可以百度搜下题解就有. 这里给出介绍unique函数的链接:http://www.cnblogs.com/zhangshu/archiv ...