最长公共子序列
问题描述
求数组A和B的最长公共子序列
问题分析
- 子序列(subsequence): 一个特定序列的子序列就是将给定序列中零个或多个元素去掉后得到的结果(不改变元素间相对次序)。例如序列<A,B,C,B,D,A,B>的子序列有:<A,B>、<B,C,A>、<A,B,C,D,A>等。
- 公共子序列(common subsequence): 给定序列X和Y,序列Z是X的子序列,也是Y的子序列,则Z是X和Y的公共子序列。例如X=[A,B,C,B,D,A,B],Y=[B,D,C,A,B,A[,那么序列Z=[B,C,A]为X和Y的公共子序列,其长度为3。但Z不是X和Y的最长公共子序列,而序列[B,C,B,A]和[B,D,A,B]也均为X和Y的最长公共子序列,长度为4,而X和Y不存在长度大于等于5的公共子序列。对于序列[A,B,C]和序列[E,F,G]的公共子序列只有空序列[]。
- 最长公共子序列:给定序列X和Y,从它们的所有公共子序列中选出长度最长的那一个或几个。
- 子串: 将一个序列从最前或最后或同时删掉零个或几个字符构成的新系列。区别与子序列,子序列是可以从中间抠掉字符的。cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列

策略选择
算法设计
设X=x1,x2,x3,x4…,xm,Y=y1,y2,y3,y4…,yn为两个序列,Z=z1,z2,z3,z4…,zk是他们的任意公共子序列.所以如果用一个二维数组C表示字符串X和Y中对应的前i,前j个字符的LCS的长度话。

算法分析
算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #include <iostream> #include <string> #include <stack> using namespace std; void LCS(string s1,string s2) { int m=s1.length()+1; int n=s2.length()+1; int **c; int **b; c=new int* [m]; b=new int* [m]; for(int i=0;i<m;i++) { c[i]=new int [n]; b[i]=new int [n]; for(int j=0;j<n;j++) b[i][j]=0; } for(int i=0;i<m;i++) c[i][0]=0; for(int i=0;i<n;i++) c[0][i]=0; for(int i=0;i<m-1;i++) { for(int j=0;j<n-1;j++) { if(s1[i]==s2[j]) { c[i+1][j+1]=c[i][j]+1; b[i+1][j+1]=1; } else if(c[i][j+1]>=c[i+1][j]) { c[i+1][j+1]=c[i][j+1]; b[i+1][j+1]=2; } else { c[i+1][j+1]=c[i+1][j]; b[i+1][j+1]=3; } } } for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { cout<<c[i][j]<<' '; } cout<<endl; } stack<char> same; stack<int> same1,same2; for(int i = m-1,j = n-1;i >= 0 && j >= 0; ) { if(b[i][j] == 1) { i--; j--; same.push(s1[i]); same1.push(i); same2.push(j); } else if(b[i][j] == 2) i--; else j--; } cout<<s1<<endl; for(int i=0;i<m && !same1.empty();i++) { if(i==same1.top()) { cout<<1; same1.pop(); } else cout<<' '; } cout<<endl<<s2<<endl; for(int i=0;i<n && !same2.empty();i++) { if(i==same2.top()) { cout<<1; same2.pop(); } else cout<<' '; } cout<<endl<<"最长公共子序列为:"; while(!same.empty()) { cout<<same.top(); same.pop(); } cout<<endl<<"长度为:"<<c[m-1][n-1]<<endl; for (int i = 0; i<m; i++) { delete [] c[i]; delete [] b[i]; } delete []c; delete []b; } int main() { string s1="ABCPDSFJGODIHJOFDIUSHGD"; string s2="OSDIHGKODGHBLKSJBHKAGHI"; LCS(s1,s2); return 0; }
|