• 最长公共子序列


    同样,注意和最长公共子字符串的区别,子序列没有字符连续的要求。问题描述如下:

    给定两个字符串str1和str2,求二者的最长公共子序列,一个具体的实例说明是若str1 = “13546”,str2 =“2153467”,那么他们的最长公共子序列为“1346”。

    这是算法导论上用来介绍动态规划的时候一个很经典的问题,怎么看有没有最优子结构呢?构建一张表count,count[i][j]表示str1[0,…,i]和str2[0,…,j]的最长子序列,分析如下:

    假定现在需求str1[0,…,i]和str2[0,…,j]的最长子序列,那么有以下几种情况:

    1.str1[i] ==str2[j] : 此时count[i][j] =count[i-1][j-1]

    2.str1[i] != str2[j] : 此时 count[i][j] =max(count[i-1][j],count[i][j-1]

    一个例子如下:

    image

    上图中 e表示边界,m表示 往做左上角转,l表示left,u表示up。

    与之相对应的代码如下:

    int lcs_sequence(char *str1,char *str2,int str1_len,int str2_len)
    {
            
        //动态规划表
        char *count  = (char *)malloc(str2_len*str1_len*sizeof(char));
        char *record = (char *)malloc(str2_len*str1_len*sizeof(char));
     
        //分别记录当前最长的子序列长度 和 轨迹
     
        for(int h =0;h<str1_len;h++)
        {
            for(int w=0;w<str2_len;w++)
            {
                if(str1[h]==str2[w])
                {
                
                    if(h==0 || w==0)
                    {
                        count[h*str2_len+w] = 1;
                        record[h*str2_len+w] = 'm';    
                    }
                    else
                    {
                        count[h*str2_len+w] = count[(h-1)*str2_len+w-1]+1;
                        record[h*str2_len+w] = 'm';        
                    }
                    
                }
                else
                {
                    if(h == 0 || w ==0)
                    {
                        count[h*str2_len+w] = 0;
                        record[h*str2_len+w] = 'e';    
                    }
                    else
                    {
                        if(count[(h-1)*str2_len+w]>count[h*str2_len+w-1])
                        {
                            count[h*str2_len+w] = count[(h-1)*str2_len+w];
                            record[h*str2_len+w] = 'u';
                        }
                        else
                        {
                            count[h*str2_len+w] = count[h*str2_len+w-1];
                            record[h*str2_len+w] = 'l';
                        }
     
                    }
                }
            }
        }
     
    //按照轨迹输出
     
        int maxSubSeqLen = count[str1_len*str2_len-1];
        char * result = (char *)malloc((maxSubSeqLen+1)*sizeof(char));
        result[maxSubSeqLen] = '';
        int cur = maxSubSeqLen-1;
        int i= str1_len-1;int j =str2_len-1;
     
        while(true)
        {
            if(i<0||j<0)break;
            if(record[i*str2_len+j] == 'm') 
            {
                printf("%c
    ",str2[j] );
                result[cur] = str2[j];
                i--;j--;cur--;
            }
            if(record[i*str2_len+j] == 'e')break; 
            if(record[i*str2_len+j] == 'l')
            {
                j--;
            }
            if(record[i*str2_len+j] == 'u')
            {
                i--;
            } 
     
        }
     
     
        printf("
    the longest common subseq is : %s (length = %d)",result,maxSubSeqLen);
     
        return maxSubSeqLen;
     
    }
  • 相关阅读:
    228. Summary Ranges
    227. Basic Calculator II
    224. Basic Calculator
    222. Count Complete Tree Nodes
    223. Rectangle Area
    221. Maximal Square
    220. Contains Duplicate III
    219. Contains Duplicate II
    217. Contains Duplicate
    Java编程思想 4th 第4章 控制执行流程
  • 原文地址:https://www.cnblogs.com/obama/p/3224120.html
Copyright © 2020-2023  润新知