zoukankan      html  css  js  c++  java
  • 顺序对齐的N^2算法

      顺序对齐

    考虑两个字符串右对齐的最佳解法。例如,有一个右对齐方案中字符串是AADDEFGGHC和ADCDEGH。
    AAD_DEFGGHC
     ADCDE__GH_
    每一个数值匹配的位置值2分,一段连续的空格值-1分。所以总分是匹配点的2倍减去连续空格的段数,在上述给定的例子中,6个位置(A,D,D,E,G,H)匹配,三段空格,所以得分2*6+(-1)*3=9,注意,我们并不处罚左边的不匹配位置。若匹配的位置是两个不同的字符,则既不得分也不失分。
    请你写个程序找出最佳右对齐方案。

    输入
    输入文件包含两行,每行一个字符串,最长3000个字符。字符全部是大字字母。

    输出
    一行,为最佳对齐的得分。  

    样例
    输入:
    AADDEFGGHC
    ADCDEGH
    输出:
    9

    这道题从dp的角度去思考

    发现可以硬想出一种方法

    dp(i,j)表示第一个串的前i项,和第二个串的前j项所构成右对齐方案中代价最大的量

    所以

    1.dp(i,j)=dp(i-1,j-1)+(2/0)<这个根据i,j的情况来确定

    2.dp(i,j)=dp(i,k)-1(1<=k<j)

    3.dp(i,j)=dp(k,j)-1(1<=k<i)

    dp(i,j)=max{1,2,3};

    然后发现这个算法是错的因为这个算法的时间复杂度为O(n^3)

    所以我们要思考如何不枚举“-”号;

    基于这个思想,我们想到了继承;

    dp(i,j,0,0)表示第一个串的前i项,和第二个串的前j项所构成右对齐方案中i,j右方都没有空格代价最大的量

    dp(i,j,1,0)表示第一个串的前i项,和第二个串的前j项所构成右对齐方案中i,右方有空格,而j右方每空格的代价最大的量

    dp(i,j,0,1)同上

    那么状态如何转移呢

    我认为大家都想到了。

    然后就是代码,用迭代实现

    //#include<cstdio>
    //#include<algorithm>
    //#include<cstring>
    //#define N 3000+10
    //using namespace std;
    //int f[N][N];
    //char s1[N],s2[N];
    //int dp(int i,int j)
    //{
    //    if(i==0||j==0)return 0;
    //    if(f[i][j])return f[i][j];
    //    if(s1[i]==s2[j]) f[i][j]=dp(i-1,j-1)+2;
    //    f[i][j]=max(f[i][j],dp(i-1,j-1));
    //    for(int k=1;k<i;k++)f[i][j]=max(f[i][j],dp(k,j)-1);
    //    for(int k=1;k<j;k++)f[i][j]=max(f[i][j],dp(i,k)-1);
    //    return f[i][j];
    //    
    //}
    //int main()
    //{
    //    scanf("%s%s",s1+1,s2+1);
    //    int len1=strlen(s1+1),len2=strlen(s2+1);
    ////    for(int i=1;i<=len1;i++)
    ////        for(int j=1;j<=len2;j++)
    ////        {
    ////            if(f[i][j]){printf("%d %d:",i,j);printf("%d
    ",f[i][j]);}
    ////        }
    //    printf("%d",dp(len1,len2));
    //    return 0;
    //}
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 3000+10
    using namespace std;
    char a[N],b[N];
    int  f[N][N][2][2],l1,l2;
    int main()
    {
        scanf("%s%s",a+1,b+1);
        l1=strlen(a+1); l2=strlen(b+1);
        f[0][0][0][0] = 1;
        for(int i=1;i<=l1;i++)
         for(int j=1;j<=l2;j++)
          {
              int t[10];
              for (int k = 0; k < 6; ++k) t[k] = -1e9;
               if(a[i]==b[j]) 
               {
                t[0]=f[i-1][j-1][0][0]+2;
                t[1]=f[i-1][j-1][1][0]+2;
                t[2]=f[i-1][j-1][0][1]+2;
               }
               if(a[i]!=b[j])
               {
                   t[3]=f[i-1][j-1][0][0];
                   t[4]=f[i-1][j-1][1][0];
                   t[5]=f[i-1][j-1][0][1];
               }
                   t[6]=f[i][j-1][0][0]-1;
                   t[7]=f[i][j-1][1][0];
                   t[8]=f[i-1][j][0][0]-1;
                   t[9]=f[i-1][j][0][1];
                   for(int k=0;k<=5;k++)
                       f[i][j][0][0]=max(f[i][j][0][0],t[k]);
                   f[i][j][1][0]=max(t[6],t[7]);
                f[i][j][0][1]=max(t[8],t[9]);       
          } 
          int ans=max(f[l1][l2][0][0],max(f[l1][l2][1][0],f[l1][l2][0][1]));
          printf("%d",ans);
        return 0;
    }

    这种想法很重要,运用范围很广,主要就是增加半维来使相同的枚举量减少

  • 相关阅读:
    NOIP 2018 day1 题解
    公司管理与信息化基础成熟度模型
    信息化成熟度整体评估模型
    审计抽样
    正态分布
    函证决策
    SALESORDERINCOME.QVW
    ERP上线通用模板
    可转换债券分拆
    luogu 1373 小a和uim之大逃离 dp
  • 原文地址:https://www.cnblogs.com/star-eternal/p/7552206.html
Copyright © 2011-2022 走看看