• 2014年9月28日 18:35:01


    着实是有好几天没有动手写写自己的博客了。这些天感觉自己是被别人的事情搞的一团糟,结果自己反倒是帮不上什么忙的。还是算了吧,先将自己的东西好好的忙好,毕竟还是得自己有能力才能够帮到别人的,没办法,物竞天择适者生存。

    好了,ACM也是告了一个段落,结果等来等去等到了算法课,最终是让自己失望万分,还是赶紧的重操旧业把,好好努力,争取让自己搞出一点成绩来,即使最后是失败了,也是虽败犹荣,亮剑精神嘛。

    今天研究的问题是最长公共子序列,着实由于基础不扎实,网上找了一篇博客,现在将它的解决方案列举出来:

    方法一:枚举法

    主要是将第一个串的所有的子序列全部都列举出来,然后和第二个串进行匹配,这个属于暴力破解法。

    方法二:动态规划

    这里楼主采用的是矩阵的方式来实现的,也就是二维数组。

    先是计算最长公共子序列的长度,然后是根据长度回溯出最长公共子序列。

    现有两个序列X={x1,x2,x3,...xi},Y={y1,y2,y3,....,yi},

    设一个C[i,j]: 保存Xi与Yj的LCS的长度。

    递推方程为:

    不知道大家看懂了没?动态规划的一个重要性质特点就是解决“子问题重叠”的场景,可以有效的避免重复计算,根据上面的

    公式其实可以发现C[i,j]一直保存着当前(Xi,Yi)的最大子序列长度。

     1 #include<stdio.h>
     2 #include<string.h>
     3 char a[30],b[30];
     4 int lena,lenb;
     5 int LCS(int,int);  ///两个参数分别表示数组a的下标和数组b的下标
     6 
     7 int main()
     8 {
     9     strcpy(a,"ABCBDAB");
    10     strcpy(b,"BDCABA");
    11     lena=strlen(a);
    12     lenb=strlen(b);
    13     printf("%d
    ",LCS(0,0));
    14     return 0;
    15 }
    16 
    17 int LCS(int i,int j)
    18 {
    19     if(i>=lena || j>=lenb)
    20         return 0;
    21     if(a[i]==b[j])
    22         return 1+LCS(i+1,j+1);
    23     else
    24         return LCS(i+1,j)>LCS(i,j+1)? LCS(i+1,j):LCS(i,j+1);
    25 }

     下面的这个是根据公式优化出来的代码:

     1 #include <iostream>
     2 #include <string>
     3 #include<stdio.h>
     4 #include<string.h>
     5 
     6 
     7 char a[500],b[500];
     8 char num[501][501]; ///记录中间结果的数组
     9 char flag[501][501];    ///标记数组,用于标识下标的走向,构造出公共子序列
    10 void LCS(); ///动态规划求解
    11 void getLCS();    ///采用倒推方式求最长公共子序列
    12 
    13 using namespace std;
    14 
    15 int main()
    16 {
    17     int i;
    18     strcpy(a,"zhangjie");
    19     strcpy(b,"hetongkang");
    20     memset(num,0,sizeof(num));
    21     memset(flag,0,sizeof(flag));
    22     LCS();
    23     printf("%d
    ",num[strlen(a)][strlen(b)]);
    24     getLCS();
    25     return 0;
    26 }
    27 
    28 void LCS()
    29 {
    30     int i,j;
    31     for(i=1;i<=strlen(a);i++)
    32     {
    33         for(j=1;j<=strlen(b);j++)
    34         {
    35             if(a[i-1]==b[j-1])   ///注意这里的下标是i-1与j-1
    36             {
    37                 num[i][j]=num[i-1][j-1]+1;
    38                 flag[i][j]=1;  ///斜向下标记
    39             }
    40             else if(num[i][j-1]>num[i-1][j])
    41             {
    42                 num[i][j]=num[i][j-1];
    43                 flag[i][j]=2;  ///向右标记
    44             }
    45             else
    46             {
    47                 num[i][j]=num[i-1][j];
    48                 flag[i][j]=3;  ///向下标记
    49             }
    50         }
    51     }
    52 }
    53 
    54 void getLCS()
    55 {
    56 
    57     char res[500];
    58     int i=strlen(a);
    59     int j=strlen(b);
    60     int k=0;    ///用于保存结果的数组标志位
    61     while(i>0 && j>0)
    62     {
    63         if(flag[i][j]==1)   ///如果是斜向下标记
    64         {
    65             res[k]=a[i-1];
    66             k++;
    67             i--;
    68             j--;
    69         }
    70         else if(flag[i][j]==2)  ///如果是斜向右标记
    71             j--;
    72         else if(flag[i][j]==3)  ///如果是斜向下标记
    73             i--;
    74     }
    75 
    76     for(i=k-1;i>=0;i--)
    77         printf("%c",res[i]);
    78 }
    我要坚持一年,一年后的成功才是我想要的。
  • 相关阅读:
    看了陈安之的文字 无论怎样 都要记住的是 你仍然是你自己 改变是应用他人的方法提高自己 改变是做更优秀更独特的自己
    流行的Ajax应用演示和源码下载(转)
    WEB2.0概念诠释(根据网络资料归纳)之一
    ASP.NET中文件上传下载方法集合(较为详细的介绍 转)
    建立梦想清单
    Ajax的应用
    Ajax的问题
    WEB2.0概念诠释(根据网络资料归纳)之三
    IIS突然挂掉
    VS2008软件90天过期,解决升级问题。
  • 原文地址:https://www.cnblogs.com/tianxia2s/p/3998817.html
Copyright © 2020-2023  润新知