当前位置:首页 » 公共卫生 » 最长公共子序列算法

最长公共子序列算法

发布时间: 2021-03-08 17:24:20

① 最长公共子串和最长公共子序列的区别

/* 目标:输出两个字符串的所有公共最长子序列
date: 09-11-26
BY: zggxjxcgx
算法: 判断较短串是否为较长串的子序列,如果是则得到结果;
否则,对较短串进行逐个字符删除操作(将字符替换为'#'表示删除)。
删除操作用递归函数进行实现。每层递归删除一个字符,
若删除一个字符后未得到匹配子序列,则还原该字符所在位置。
第n层递归未找到匹配子序列,则将递归层数加1,重复删除直到剩下空串。

*/
#include<stdio.h>
#include<string.h>
int dep=0; /* 较短串的长度 */
int depflag=0; /*下一步要探测的深度 */
int lastflag=0; /* 是否找到匹配子序列,1为找到 */
int count=0; /* 目标结果的个数 */

int mystrcmp(char *s1,char *s2) /* 判断s2是否为 s1的子串 */
{ while(*s1 *s2)
if(*s2=='#') s2++;
else if(*s2 == *s1) { s1++; s2++; }
else s1++;

while(*s2=='#') s2++;
if(*s2=='\0') return 1;
return 0;
}
void pristr(char *str) /* 打印最长子序列 */
{ if(0==count++) printf("\n公共最长子序列:\n");
printf("%2d:",count);
while(*str)
{ if(*str!='#')
printf("%c",*str);
str++;
}
printf("\n");
}

/*递归函数求最长子序列。start 控制下一个要检测的字符,deptemp控制递归的深度,first为's'表示第一层递归 */
int fun(char *str1,char *str2,char *start,int deptemp,char first)
{ int i=0,j=0;
char *s,cback;
do
{ s=start;
if('s'==first) deptemp=depflag; /* 在第一层设置递归深度 */
while(*s)
{ if(*s=='#') { s++; continue; }
cback=*s; *s='#'; /* 删除当前字符*/
if(mystrcmp(str1,str2)) { pristr(str2); lastflag=1; } /*找到匹配,将lastflag设为1,在完成深度为deptemp+1的探测(找到所有匹配)后退出递归 */
else if(deptemp>0) fun(str1,str2,s+1,deptemp-1,'n'); /* 深度探测,s+1表示从下一个位置开始删除 */
*s=cback; s++; /* 还原该位置的字符,以便下次进行探测 */
}
if('s'==first) ++depflag; /* 删除depflag+1个字符还未找到,则递归深度加1 */
}while(depflag<dep-1 's'==first 0==lastflag); /* 第一层递归具有特殊意义,由三个变量标记是否第一层 */
if(lastflag) return 1; /* lastflag 为1 表示找到匹配子序列 */
return 0;
}
void main()
{ char *s1,*s2;
char st1[]="asfdebjewcwedwk";
char st2[]="sabscdkwss"; // kwfsa
if(strlen(st1)>strlen(st2)) s1=st1,s2=st2; /* 将s1设为较长的串 */
else s1=st2,s2=st1;

printf("\nstr1:%s\nstr2:%s\n",s1,s2);
dep=strlen(s2); /* 得到较短串的长度 */
if(mystrcmp(s1,s2)) pristr(s2);
else if(0==fun(s1,s2,s2,0,'s')) printf("\n没有公共元素!\n");
// printf("%d\n",mystrcmp("afdebjewcwedw","abcdw#"));
}

② 用C++求最长公共子序列问题

什么意思,连续的还是求交集?

③ 求最长公共子序列的c语言代码

???

④ 求数组的最大子数组值和最长公共子序列问题

a) 最长公共子序列的结构
若用穷举搜索法,耗时太长,算法需要指数时间。
易证最长公共子序列问题也有最优子结构性质
设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,则:
i. 若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
ii. 若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
iii. 若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。
其中Xm-1=<x1, x2, …, xm-1>,Yn-1=<y1, y2, …, yn-1>,Zk-1=<z1, z2, …, zk-1>。
最长公共子序列问题具有最优子结构性质。

⑤ 最长 公共子序列问题(算法分析 C++)

#include <iostream>
#include <string>
using namespace std;
//主函数
int main()
{
int m,n;
char *x,*y;
int **b,**c;
void LCSLength(int m,int n,char *y,char *x,int **c,int **b);
void LCS(int i,int j,char *x,int**b);

cout<<"请输入两个序列的长度:"<<endl;
cin>>m>>n;
x=new char[m];
y=new char[n];
cout<<"请输入两个序列:"<<endl;
cin>>x>>y;
b=new int *[m + 1]; // 注意这里,原式没有+1
for (int i=0;i<=m;i++)
b[i]=new int[n + 1]; // 注意这里,原式没有+1
c=new int *[m + 1];
for (int j=0;j<=m;j++)
c[j]=new int[n + 1]; // 注意这里,原式没有+1
LCSLength(m,n,x,y,c,b);
cout<<"最长公共子序列的元素个数为"<<c[m][n]<<endl;
cout<<"该序列为:";
LCS(m,n,x,b); //注意后面的内容是清理,暂时先跳过去,你先搞定主程序先
/* delete []x;
delete []y;
for(int k=0;k<=m;k++)
delete []b[k];
delete []b;
for(int h=0;h<=m;h++)
delete []c[h];
delete []c;
*/
return 0;
}
//计算最优值
void LCSLength(int m,int n,char *y,char *x,int **c,int **b)
{
int i,j;
for(i=1;i<=m;i++)c[i][0]=0;
for(j=0;j<=n;j++)c[0][j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}
else if(c[i-1][j]>=c[i][j-1]){c[i][j]=c[i-1][j];b[i][j]=2;}
else {c[i][j]=c[i][j-1];b[i][j]=3;}
}
}
//构造最长公共子序列
void LCS(int i,int j,char *x,int**b)
{
if(i==0||j==0)return;
if(b[i][j]==1){LCS(i-1,j-1,x,b);cout<<x[i];}
else if(b[i][j]==2)LCS(i-1,j,x,b);
else LCS(i,j-1,x,b);
}

⑥ (算法 c++)动态规划法求解最长公共子序列 本人菜鸟求高手改错帮忙完成 谢谢了

不是我不想帮你,但如果真要改的话,整个程序差不多要重写了……首先你要确定此程序是上网刷题/比赛?还是自学算法知识?如果你有很好的数学功底还可以自学知识,但比赛的话自学是绝对不够的,那需要充分的交流,还有,养成良好的编程风格是一个极其重要的方面,在网上应该可以找到某些大牛的代码集,运气好还有注释版的,可以多多借鉴。下面是一段代码,NetBeans/G++编译通过,你可以尝试改成类结构的。^_^

#include <iostream>

using namespace std;

#define MAXLENGTH 20

// 这是偷懒的部分……不要介意哈
int maxLength[MAXLENGTH + 2][MAXLENGTH + 2];
int preChar[MAXLENGTH + 2][MAXLENGTH + 2];

/*
* 参数说明
* s1:待处理字符串1
* s2:待处理字符串2
* l1:s1长度(不包括字符串结束符'/0')
* l2:s2长度(不包括字符串结束符'/0')
*
* 参数中加const的目的是为了保护外部数据,防止因失误而在函数内部改变了本因无需改变的数值。
*/
int LCSLength(const char* s1, const int l1, const char* s2, const int l2) {

/* 尽量不要在for等语句中定义变量,每个函数一开始最好就把需要的变量全部定义好,同时尽量赋予有意义的函数名 */
/* 当然,有时偷点懒是可以的,但你要确保过了几个月后一看到代码就能很快知道这是啥意思 */
int i, j;
/* maxLength用于存放中间数据,意义:maxLength[i][j]表示:s1前i个字符与s2前j个字符的最长子序列长度
* preChar用于存放当前最长子序列是由那一个自序列得来的
* 因本算法特殊性,需要各额外2位的存储空间
*/

/**/
for (i = 0; i <= l1; i++) maxLength[i][0] = 0;
for (j = 0; j <= l2; j++) maxLength[0][j] = 0;
for (i = 0; i <= l1; i++)
for (j = 0; j <= l2; j++) {
/* 如果s1第i个字符与s2第j个字符相同,则更新maxLength[i+1][j+1]存储的最大值,和preChar存放的前缀自序列位置
* 下同
*/
if (s1[i] == s2[j] && maxLength[i + 1][j + 1] < maxLength[i][j] + 1) {
maxLength[i + 1][j + 1] = maxLength[i][j] + 1;
preChar[i + 1][j + 1] = 1;
}
if (maxLength[i + 1][j] < maxLength[i][j]) {
maxLength[i + 1][j] = maxLength[i][j];
preChar[i + 1][j] = 2;
}
if (maxLength[i][j + 1] < maxLength[i][j]) {
maxLength[i][j + 1] = maxLength[i][j];
preChar[i][j + 1] = 3;
}
}

/* 返回最长子序列长度 */
return maxLength[l1][l2];
}

/**
* s1、s2与上同
* i:s1当前字符序号
* j:s2当前字符序号
*
* i、j初始值为各自字符串长度
*/
void LCSOutput(const char* s1, const int i, const char* s2, const int j) {

if (i >= 0 && j >= 0) {

// 由于是逆向输出,所以先递归,后输出
switch (preChar[i][j]) {
case 1:
LCSOutput(s1, i - 1, s2, j - 1);
break;
case 2:
LCSOutput(s1, i - 1, s2, j);
break;
case 3:
LCSOutput(s1, i, s2, j - 1);
break;
default:
break;
}

if (s1[i] == s2[j])
cout << s1[i];
}
}

int main() {

cout << "最长公共子序列长度:" << LCSLength("1234567890", 10, "1358967", 7) << endl;

cout << "最长公共子序列(不确保唯一):";
LCSOutput("1234567890", 10, "1358967", 7);
cout << endl;

return 0;
}

⑦ 我想问一下在算法设计(如图)计算最长公共子序列中用动态规划计算复杂度不也是(m*n),如果我拿X中

如果要两个字符串是不是有相同的字符,那么是m*n,只是如果是子序列,每次扫描到相同的字符还要继续往后扫描,这个是指数增长的

⑧ 最长公共子序列的c++代码实现

//最大公共子序列

#include<iostream>
#include<string>
using namespace std;

void LCSLength(int m, int n, string &x, string &y,int ** c, int **b)
{
int i,j;
for( i=1;i<=m;i++) c[i][0]=0;
for( i=1;i<=n;i++) c[0][i]=0;
cout<<"111"<<endl;
for( i=1;i<=m;i++)
for( j=1;j<=n;j++)
{
if( x[i-1]==y[j-1] )
{
c[i][j] = c[i-1][j-1]+1;
b[i][j]=1;
}
else
{
if( c[i-1][j] >= c[i][j-1] )
{
c[i][j] = c[i-1][j];
b[i][j]=2;
}
else
{
c[i][j] = c[i][j-1];
b[i][j]=3;
}
}

}
}

void LCS(int i, int j, string& x, int **b, string &result)
{
if(i==0 || j==0) return;
if(b[i][j] == 1)
{
LCS(i-1,j-1,x,b,result);
result+=x[i-1];
}
else
{
if(b[i][j] == 2)
LCS(i-1,j,x,b,result);
else
LCS(i,j-1,x,b,result);
}
}

string dp(string &x,string &y,string & result)
{
int m=x.size();
int n=y.size();

int **c=new int*[m+1];
for(int i=0;i<=m;i++)
c[i]=new int[n+1];

int **b=new int*[m+1];
for(int i=0;i<=m;i++)
b[i]=new int[n+1];

c[0][0]=0;
LCSLength(m, n, x, y, c, b);

LCS(m, n, x, b, result);
return result;

}

int main()
{
//
string x="find";

string y="fnid";
string result="";
dp(x,y,result);

cout<<x<<endl;
cout<<y<<endl;
cout<<result<<endl;
return 1;
}

⑨ 求最长公共子序列的C语言程序

得到字符串m1,m2后,有一个为空则子列为空。

如果都不为空,开始下面的步骤。

求得两列的长度分别为n1,n2。

动态生n2行n1列矩阵(二维数组)。

取m2中每个元素(记位置为i)与m1中元素(记位置为j)逐个比较,如果相等则为矩阵中相应行列坐标的元素赋值为1,否则为0(可用循环嵌套完成)。

比如m1(abc0cbad)m2(cba1abc)两串的话,可以得到如图所示矩阵。

然后,不难看出,要进行如下步骤。

定义max,用来记录最大子列中元素个数。

定义数组l[n2],用来记录最大子列的首字符地址(因为可能有不同最大子列,故用数组,而不是单个变量)。

判断矩阵中每一个元素,是否为1,如果是则记下此时行地址到l数组,然后判断相对于这个元素的下一行下一列的元素是否为1,如果是则继续判断,一直到为0。记下此次判断(即一个while循环)中“1”的个数n,存入变量max。

对于矩阵中的每一个元素都这么判断,如果判断中n的值大于max那么把n付给max,同时把这个子列的首地址付给l[0],l[0]后面的元素全赋值为-1。如果,某次判断得到的n与max相同,即有相同最大子列,那么把它的首地址存入l数组的下一个位置。

当这个矩阵的每一个元素都判断完毕后,会得到max,和数组l,然后用循环做如下输出过程:依次以l数组中的每个元素为首地址,输出m2字符串中以相应序号开头的max个字符,那么完成所有最大子列的输出。

昨天失眠了,一直到今天凌晨3点多,脑袋浑浑噩噩的,本想帮你敲代码,可是脑力不支了,估计敲出来也乱,还有问题的话,再讨论452032545

⑩ 最长公共子序列的空间时间优化算法

楼主你好 这么专业的问题 只能 去问专业人 士 在这里 的不到答案的啊

热点内容
影视转载限制分钟 发布:2024-08-19 09:13:14 浏览:319
韩国电影伤口上纹身找心里辅导 发布:2024-08-19 09:07:27 浏览:156
韩国电影集合3小时 发布:2024-08-19 08:36:11 浏览:783
有母乳场景的电影 发布:2024-08-19 08:32:55 浏览:451
我准备再看一场电影英语 发布:2024-08-19 08:14:08 浏览:996
奥迪a8电影叫什么三个女救人 发布:2024-08-19 07:56:14 浏览:513
邱淑芬风月片全部 发布:2024-08-19 07:53:22 浏览:341
善良妈妈的朋友李采潭 发布:2024-08-19 07:33:09 浏览:760
哪里还可以看查理九世 发布:2024-08-19 07:29:07 浏览:143
看电影需要多少帧数 发布:2024-08-19 07:23:14 浏览:121