• POJ 1159 Palindrome 回文 DP


    给一个字符串,求插入最少的字符使之成为回文,回文就是顺着读和逆着读是一样的。。。

    针对这个性质,把一个字符串化为两个,一个顺着,一个逆着,然后找一次最长公共子序列,插入的最少字符数即为字符串的长度-最长公共子序列的长度。

    另一种做法(我自己想太多),是从2序列比对中找的灵感,和最长公共子序列的做法差不多,但是效果不好,2序列比对可用来解再复杂一点点的问题会更好。。。2序列比对,中间有插入,删除,替换三种操作,给每种操作(比对)赋予代价值。。求两个序列的最优比对值

    照抄《算法设计与分析导论》中P140

    转移方程为见代码中的注释:

    贴代码:

    先贴LCS的代码:

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #define N 5005
     4 char a[N];
     5 int d[2][N];
     6 int max(int x,int y)
     7 {
     8     return x>y?x:y;
     9 }
    10 int main()
    11 {
    12     int i,j;
    13     int n;
    14 //    freopen("in.cpp","r",stdin);
    15     while(~scanf("%d",&n))
    16     {
    17         scanf("%s",a);
    18         for(i=0; i<=n; ++i)
    19             d[0][i] = 0;
    20         d[1][0] = 0;
    21         int x=1;
    22         for(i=1; i<=n; ++i)
    23         {
    24             for(j=1; j<=n; ++j)
    25             {
    26                 if(a[i-1] == a[n-j])
    27                     d[x][j] = d[1-x][j-1]+1;
    28                 else
    29                     d[x][j] = max(d[1-x][j],d[x][j-1]);
    30             }
    31             x = 1-x;  //实现滚动,原来为0,现在为1,原来为1,现在为0
    32         }
    33         printf("%d\n",n-d[1-x][n]);//输出最后结果
    34     }
    35     return 0;
    36 }

    再贴2序列比对:都用了滚动数组

    View Code
     1 #include <cstdio>
     2 #define N 5005
     3 #define INF 1000000000
     4 int A[2][N];//A[i][j]表示字符串a1,a2,```,ai与字符串b1,b2,```,bj的最少插入
     5 char s[N];
     6 int f(char a,char b)
     7 {
     8     if(a == b) return 0; //a,b相等为0
     9     else return -INF;//a,b不等为负无穷,因为该题只能插入
    10     //不能替换,还有插入删除的代价为-1,插入删除是对称的,在这里
    11 }
    12 int max(int x,int y)//求两个数的最大值
    13 {
    14     return x>y?x:y;
    15 }
    16 int main()
    17 {
    18 //    freopen("in.cpp","r",stdin);
    19     int n,i,j;
    20     while(scanf("%d",&n) != EOF)
    21     {
    22         scanf("%s",s);
    23         for(i=1; i<=n; ++i)//初始化,都是插入
    24             A[0][i] = -i;
    25         A[0][0] = 0;
    26         bool x=1;
    27         A[x][0] = -1;
    28         for(i=1; i<=n; ++i)
    29         {
    30             for(j=1; j<=n; ++j)
    31             {
    32                 A[x][j] = max(A[!x][j]-1,A[x][j-1]-1);//2个状态转移方程
    33                 A[x][j] = max(A[x][j],A[!x][j-1] + f(s[i-1],s[n-j]));
    34             }
    35             x = !x;
    36             A[x][0] = A[!x][0]-1;
    37         }
    38         printf("%d\n",-A[!x][n]/2);//因为翻倍计算了,最后结果得除以2
    39     }
    40     return 0;
    41 }
  • 相关阅读:
    vue如何实现热更新
    vue项目与node项目分离
    vue如何实现热更新
    Vue项目SSR改造实战
    找工作Java面试 题搜集
    html5绘图笔记纪要
    HTML5实现绘制几何图形
    浅谈html5在vr中的应用
    浏览器三种事件处理的模型
    基于html5二个div 连线
  • 原文地址:https://www.cnblogs.com/allh123/p/3076458.html
Copyright © 2020-2023  润新知