最长公共子序列-动态规划
子序列:序列 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; }