最长公共子序列-动态规划

子序列:序列 X<A,B,C,D,E,F> , <A> <A,B> <A,C,E> <A,B,C,D,E,F>等等都为X。

最长公共子序列:两个序列的公共子序列最长的那个。

问题分析:

给定两个序列:

 

定义个C数组,存储当x1中只有0~7个元素时与y1中只有0~6个元素的最长公共子序列。

假设x1中没有元素时,最长公共子序列:0

x1中只有一个元素A时:

x1中两个元素A B时:

红框是x1中 B 与y1中 D比较,不相等,有两种情况,B的前一个元素的最大子段和 或 B与D前的最大子段和,它们取大值,代码:C[i][j] = ( C[i-1][j] > C[i][j-1]?C[i-1][j]:C[i][j-1] );

绿框是x1中 B 与y1中 B比较,相等,一种情况,x1中B前一个元素到y1中B前的最大子段和+1,代码:C[i][j] = C[i-1][j-1]+1;

 最后得出C数组:                                                                             

                                                                 rec数组: 从下标结尾开始,if=0,向上移;if=1,a[i]值存入c数组;if=-1,向左移。

                                

输入:

7 6
A B C B D A B
B D C A B A

输出:

B C B A
4

代码:

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

int main()
{
    int rec[100][100];//记录最大子段和字符位置
    char a[100],b[100],c[100];//c数组存储最后最大子段和的字符
    int C[100][100]= {0};//记录最大子段和
    int len_a,len_b;
    cin>>len_a>>len_b;
    for(int i=1; i<=len_a; i++)
    {
        cin>>a[i];
    }
    for(int i=1; i<=len_b; i++)
    {
        cin>>b[i];
    }
    for(int i=1; i<=len_a; i++)
    {
        for(int j=1; j<=len_b; j++)
        {
            if(a[i]==b[j])
            {
                C[i][j]=C[i-1][j-1]+1;
                rec[i][j]=1;
            }
            else
            {
                C[i][j]=(C[i-1][j]>C[i][j-1]?C[i-1][j]:C[i][j-1]);
                if(C[i][j]==C[i-1][j])
                {
                    rec[i][j]=0;
                }
                else
                {
                    rec[i][j]=-1;
                }
            }
        }
    }
    //将最大子段和的字符存入c数组
    int i=len_a,j=len_b,num=C[i][j];
    while(num>0)
    {
        if(rec[i][j]==1)
        {
            c[num--]=a[i];
            i--,j--;
        }
        else if(rec[i][j]==0)
        {
            i--;
        }
        else
        {
            j--;
        }
    }
    //输出最大子段和字符
    for(i=1;i<=C[len_a][len_b];i++)
    {
        cout<<c[i]<<" ";
    }
    cout<<endl;
    cout<<C[len_a][len_b];  //输出最大子段和个数
    return 0;
}
原文地址:https://www.cnblogs.com/xxaf/p/12887844.html