最长公共子序列问题模板(不要求连续)
2016-08-02 15:36
267 查看
首先我贴个简单的模板,用dfs来解决的
有时候我们需要把公共子序列求出
下面是最长公共子序列nlogn算法,有可能退化,转自bin314 的BLOG
最长公共子序列问题:
给定2个字符串,求其最长公共子串。如abcde和dbada的最长公共字串为bd。
动态规划:dp[i][j]表示A串前i个和B串前j个的最长公共子串的长度。
则
若A[i] == B[j] , dp[i][j] = dp[i-1][j-1] + 1;
否则 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
时间复杂度O(N*M)。
dp[i][j]仅在A[i]==B[j]处才增加,对于不相等的地方对最终值是没有影响的。
故枚举相等点处可以对其进行优化。
则对于dp[i][j](这里只计算A[i]==B[j]的i和j),取最大的dp[p][q],满足(p
int LCS(int i,int j) { if(i>=lena || j>=lenb) return 0; if(a[i]==b[j]) return 1+LCS(i+1,j+1); else return LCS(i+1,j)>LCS(i,j+1)? LCS(i+1,j):LCS(i,j+1); } //用的时候是LCS(0,0)
有时候我们需要把公共子序列求出
void LCS() { int i,j; for(i=1;i<=strlen(a);i++) { for(j=1;j<=strlen(b);j++) { if(a[i-1]==b[j-1]) ///注意这里的下标是i-1与j-1 { num[i][j]=num[i-1][j-1]+1; flag[i][j]=1; ///斜向下标记 } else if(num[i][j-1]>num[i-1][j]) { num[i][j]=num[i][j-1]; flag[i][j]=2; ///向右标记 } else { num[i][j]=num[i-1][j]; flag[i][j]=3; ///向下标记 } } } } void getLCS() { char res[500]; int i=strlen(a); int j=strlen(b); int k=0; ///用于保存结果的数组标志位 while(i>0 && j>0) { if(flag[i][j]==1) ///如果是斜向下标记 { res[k]=a[i-1]; k++; i--; j--; } else if(flag[i][j]==2) ///如果是斜向右标记 j--; else if(flag[i][j]==3) ///如果是斜向下标记 i--; } for(i=k-1;i>=0;i--) printf("%c",res[i]); }
下面是最长公共子序列nlogn算法,有可能退化,转自bin314 的BLOG
最长公共子序列问题:
给定2个字符串,求其最长公共子串。如abcde和dbada的最长公共字串为bd。
动态规划:dp[i][j]表示A串前i个和B串前j个的最长公共子串的长度。
则
若A[i] == B[j] , dp[i][j] = dp[i-1][j-1] + 1;
否则 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
时间复杂度O(N*M)。
dp[i][j]仅在A[i]==B[j]处才增加,对于不相等的地方对最终值是没有影响的。
故枚举相等点处可以对其进行优化。
则对于dp[i][j](这里只计算A[i]==B[j]的i和j),取最大的dp[p][q],满足(p
#include <stdio.h> #include <ctype.h> #include <string.h> #include <iostream> #include <string> #include <math.h> #include <vector> #include <queue> #include <algorithm> using namespace std; const int maxn = 1501 ; vector<int> location[26] ; int c[maxn*maxn] , d[maxn*maxn] ; inline int get_max(int a,int b) { return a > b ? a : b ; } //nlogn 求lcs int lcs(char a[],char b[]) { int i , j , k , w , ans , l , r , mid ; for( i = 0 ; i < 26 ; i++) location[i].clear() ; for( i = strlen(b)-1 ; i >= 0 ; i--) location[b[i]-'a'].push_back(i) ; for( i = k = 0 ; a[i] ; i++) { for( j = 0 ; j < location[w=a[i]-'a'].size() ; j++,k++) c[k] = location[w][j] ; } d[1] = c[0] ; d[0] = -1 ; for( i = ans = 1 ; i < k ; i++) { l = 0 ; r = ans ; while( l <= r ) { mid = ( l + r ) >> 1 ; if( d[mid] >= c[i] ) r = mid - 1 ; else l = mid + 1 ; } if( r == ans ) ans++,d[r+1] = c[i] ; else if( d[r+1] > c[i] ) d[r+1] = c[i] ; } return ans ; } int main() { char a[maxn] , b[maxn] ; while (~scanf("%s%s",a,b)) { printf("%d\n",lcs(a,b)); } }
相关文章推荐
- 匿名用户访问用发布站点模板创建网站的列表项时要求登录的问题解决
- LCS问题变型,要求子序列必须连续
- 匿名用户访问用发布站点模板创建网站的列表项时要求登录的问题解决
- 最长公共子序列问题(不连续)
- 经典问题:不断更新查找区间连续递增序列(区间合并模板+单点更新)(3308)
- LCS 最长公共子序列问题(非连续的)
- MDI程序,添加多文档模板,点击New菜单项的时候弹出New对话框要求让用户选择的问题
- 最长公共子序列问题(要求输出路径)
- 51Nod 1006 最长公共子序列Lcs问题 模板题
- 最长公共子序列问题(不要求连续)
- 匿名用户访问用发布站点模板创建网站的列表项时要求登录的问题解决
- 最长公共子序列问题(不连续)
- 最长公共子序列问题(不要求连续)
- 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
- DataGrid利用模板列实现自动连续编号
- 关于C++模板封装的问题(关于C++模板参数的声明)
- 数据要求说明书(转载自国家计算机标准和文件模板)
- DetailsView中模板列的一个问题:ViewState异常 "Failed to load viewstate"
- 一个XSLT的变量、参数和模板调用的问题
- Struts+Hibernate模板开发笔记---解决汉字编码问题