C++实现最长公共子序列和最长公共子串
来源:互联网 发布:java 相似度计算 编辑:程序博客网 时间:2024/05/29 02:27
C++实现最长公共子序列和最长公共子串
可能直接看上面的公式不是很能理解,下面这段话,应该很直白的解释了上面的公式,可以对比着理解下:
Xi = <x1,x2,x3,....xi> 即X序列的前i个字符(1<= i <= m)(前缀) Yj = <y1,y2,y3,....yi> 即Y序列的前j个字符(1<= j <= m)(前缀)
假定Z = <z1,z2,z3,...zk>
是LCS(X,Y)中的一个。
·若xm = yn(最后一个字符相同),则不难用反正法证明:该字符必是X与Y的任一最长公共子序列Z(设长度为k)的最后一个字符,即有zk = xm = yn,且显然有Zk-1∈LCS(Xm-1,Yn-1),即Z的前缀Zk-1是Xm-1与Yn-1的最长公共子序列。此时,问题化归成求Xm-1与Yn-1的LCS(LCS(X,Y))的长度等于LCS(Xm-1,Yn-1)的长度加1)。
·若xm≠yn,则亦不难用反证法证明:要么Z∈LCS(Xm-1, Y),要么Z∈LCS(X , Yn-1)。由于zk≠xm与zk≠yn其中至少有一个必成立,若zk≠xm则有Z∈LCS(Xm-1 , Y);类似的,若zk≠yn 则有Z∈LCS(X , Yn-1)。此时,问题化归成求Xm-1与Y的LCS及X与Yn-1的LCS。LCS(X , Y)的长度为:max{LCS(Xm-1 , Y)的长度, LCS(X , Yn-1)的长度}。
版本一:这个版本对lcs的打印比较晦涩难懂,但是只要理解还是可以看懂。
#include <iostream>#include <string>#include <vector>#include <algorithm>using namespace std;int lcs( string &str1,string &str2,vector< vector<int> >& c ){ const int len1 = str1.length(); const int len2 = str2.length(); for( int i=0;i<=len1;++i ) { for( int j=0;j<=len2;++j ) { if( !i || !j ){ c[i][j] = 0; continue; } if( str1[i-1] == str2[j-1] ) { c[i][j] = c[i-1][j-1] + 1; } else { if( c[i-1][j] > c[i][j-1] ) { c[i][j] = c[i-1][j]; } else { c[i][j] = c[i][j-1]; } } } } return c[len1][len2]; }void print_lcs( string &str1,string &str2,vector< vector<int> >& c ){ const int len1 = str1.length(); const int len2 = str2.length(); for( int i=len1,j=len2;i>=1&&j>=1; ) { if( str1[i-1] == str2[j-1] ) { cout << " " << str1[i-1]; i--; j--; continue; } if( c[i-1][j] > c[i][j-1] ) { i--; } else { j--; } }}int main(){ string str; vector <string> v; while( getline(cin,str) && !str.empty() ) { v.push_back(str); } for( vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter) { string str(*iter); reverse(str.begin(),str.end()); vector< vector<int> > c( (*iter).length() + 1,vector<int>(str.length()+1,0) ); cout << str.length() - lcs(*iter,str,c) << endl; print_lcs(*iter,str,c); } return 0;}
版本二:对lcs的打印进行优化,创建二维数组来标示,后面的循环也改成递归方式。
#include <iostream>#include <string>#include <vector>#include <algorithm>using namespace std;int lcs( string &str1,string &str2,vector< vector<int> >& vec ){ const int len1 = str1.length(); const int len2 = str2.length(); vector< vector<int> > c( len1 + 1,vector<int>(len2+1,0) ); for( int i=0;i<=len1;++i ) { for( int j=0;j<=len2;++j ) { if( !i || !j ){ c[i][j] = 0; continue; } if( str1[i-1] == str2[j-1] ) { c[i][j] = c[i-1][j-1] + 1; // 标示可打印该值 vec[i][j] = 0; } else { if( c[i-1][j] > c[i][j-1] ) { c[i][j] = c[i-1][j]; // 标示i值减一,即向上(i表示行,j表示列) vec[i][j] = 1; } else { c[i][j] = c[i][j-1]; // 标示j值减一,即向左(i表示行,j表示列) vec[i][j] = 2; } } } } return c[len1][len2]; }void print_lcs(vector< vector<int> >& vec,string str,int i,int j){ if( !i || !j ) return; // 根据上面的标示来即可 if( !vec[i][j] ) { cout << " " << str[i-1] << " "; print_lcs(vec,str,i-1,j-1); } else if( vec[i][j] == 1 ) { print_lcs(vec,str,i-1,j); } else if( vec[i][j] == 2 ) { print_lcs(vec,str,i,j-1); } }int main(){ string str; vector <string> v; while( getline(cin,str) && !str.empty() ) { v.push_back(str); } for( vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter) { string str(*iter); reverse(str.begin(),str.end()); vector< vector<int> > vec( (*iter).length() + 1,vector<int>(str.length()+1,-1) ); cout << str.length() - lcs(*iter,str,vec) << endl; print_lcs(vec,str,(*iter).length(),str.length()); cout << endl; } return 0;}
#include <iostream>#include <string>#include <vector>#include <algorithm>using namespace std;int lcs( string &str1,string &str2,vector< vector<int> >& vec ){ int result = 0; const int len1 = str1.length(); const int len2 = str2.length(); vector< vector<int> > c( len1 + 1,vector<int>(len2+1,0) ); for( int i=0;i<=len1;++i ) { for( int j=0;j<=len2;++j ) { if( !i || !j ){ c[i][j] = 0; continue; } if( str1[i-1] == str2[j-1] ) { c[i][j] = c[i-1][j-1] + 1; vec[i][j] = 0; result = c[i][j] > result ? c[i][j] : result; } } } return result; }int main(){ string str; vector <string> v; while( getline(cin,str) && !str.empty() ) { v.push_back(str); } for( vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter) { string str(*iter); reverse(str.begin(),str.end()); vector< vector<int> > vec( (*iter).length() + 1,vector<int>(str.length()+1,-1) ); cout << str.length() - lcs(*iter,str,vec) << endl; } return 0;}
参考资料:点击打开链接
阅读全文
0 0
- 最长公共子串和最长公共子序列
- 最长公共子序列和最长公共子串
- 最长公共子序列和最长公共子串
- 最长公共子串和最长公共子序列
- 最长公共子序列和最长公共子串
- 最长共公共子序列和最长公共子串
- 最长公共子序列和最长公共子串
- 最长公共子序列和最长公共子串
- 最长公共子串和最长公共子序列
- 最长公共子串和最长公共子序列
- 最长公共子序列和最长公共子串
- 最长公共子序列和最长公共子串
- 最长公共子串和最长公共子序列
- 最长公共子序列和最长公共子串区别
- 最长公共子串和最长公共子序列
- 最大子序列和、最长递增子序列、最长公共子串、最长公共子序列
- 最大子序列和、最长递增子序列、最长公共子串、最长公共子序列
- 最长公共子串和子序列
- Android studio报错:warning :uninstalling will remove the application data!
- 大数据架构师从入门到精通 学习必看宝典
- BZOJ1093 [ZJOI2007]最大半连通子图
- 第八周项目二 顺序串算法
- 实验报告二
- C++实现最长公共子序列和最长公共子串
- 用js将数组扁平化
- 单例的宏定义
- Xcode增加iOS 6和iOS 7真机支持
- 数据类型--python练习题
- 安卓数字版权管理 (DRM) 框架
- 2.spring boot配置概要
- mysql查询显示行号
- 上机练习题——接口