MATLAB 最长公共子序列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MATLAB 最长公共子序列相关的知识,希望对你有一定的参考价值。

如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中, 则字符
串一称之为字符串二的子串。
注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。 请编写一个函
数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。
例如: :输入两个字符串 ACGTAACCT 和 GGACTAGG,字符串 ACTA 是它们的最长公共子序
列,则输出它们的长度 4,并打印任意一个子序列。
然后使用编写好的程序测试两条基因序列的最长公共子序列。

参考技术A clc;clear all;clear all;
a='ACGTAACCT'-65;
b='GGACTAGG'-65;
for k=1:size(b,2)
n=k;
x=nchoosek(a,n);
y=nchoosek(b,n);
xs=size(x,1);
ys=size(y,1);
p1=1;
for i=1:xs
for j=1:ys
p=abs(x(i,:)-y(j,:));
if sum(p)==0
break;
end
end

if sum(p)==0
p1=0;
break;
end
end
if p1
break;
end
end
n=n-1;

tx=[];
x=nchoosek(a,n);
y=nchoosek(b,n);
xs=size(x,1);
ys=size(y,1);
for i=1:xs
for j=1:ys
p=abs(x(i,:)-y(j,:));
if sum(p)==0
tx=[tx;x(i,:)];
end
end
end

tx1=[0];
for i=1:n
tx1=20^(i-1)*tx(:,i)+tx1;
end
tx2=tx1(1);
tx3=1;
for i=2:length(tx1)
d=tx2(end);
if d~=tx1(i)
tx2=[tx2;tx1(i)];
tx3=[tx3;i];

end
end
tx=tx+65;
disp(['所求公共子系列为:'])
disp(char(tx(tx3,:)))本回答被提问者和网友采纳
参考技术B 用递归不好,时间慢;递归是VC的做法,MATLAB与VC不同啊,它就是用矩阵来运算的;
这样可以么?

codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)

题目描述 Description

字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij = yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。

对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数。

输入描述 Input Description

第1行为第1个字符序列,都是大写字母组成,以”.”结束。长度小于5000。

第2行为第2个字符序列,都是大写字母组成,以”.”结束,长度小于5000。

输出描述 Output Description

第1行输出上述两个最长公共子序列的长度。

第2行输出所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对100,000,000求余即可。

样例输入 Sample Input

ABCBDAB.
BACBBD.

样例输出 Sample Output

4
7

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;  
 5 
 6 #define maxn 5010  
 7 #define MOD 100000000  
 8 char A[maxn],B[maxn],cur;
 9 int f[2][maxn], g[2][maxn];
10    
11 int main()
12 {  
13     scanf("%s%s", A + 1, B + 1);
14     int na = strlen(A + 1), nb = strlen(B + 1);
15     A[na--] = \'\\0\'; B[nb--] = \'\\0\';
16     
17     cur=0;
18     for(int i = 1; i <= nb; i++) g[0][i] = 1;
19     g[0][0] = g[1][0] = 1;
20     
21     for(int i = 1; i <= na; i++)
22     {
23         cur ^= 1;  
24         for(int j = 1; j <= nb; j++)
25         {
26             if(A[i] == B[j]) f[cur][j] =f[cur^1][j-1] + 1;
27             else f[cur][j] = max(f[cur^1][j], f[cur][j-1]);
28             
29             g[cur][j] = 0;
30             if(f[cur][j] == f[cur^1][j]) g[cur][j] += g[cur^1][j];  
31             if(f[cur][j] == f[cur][j-1]) g[cur][j] += g[cur][j-1];  
32             if(f[cur][j] == f[cur^1][j] && f[cur][j] == f[cur][j-1] && f[cur^1][j-1] == f[cur][j]) 
33                 g[cur][j] -= g[cur^1][j-1];
34             if(A[i] == B[j] && f[cur][j] == f[cur^1][j-1] + 1) g[cur][j] += g[cur^1][j-1];  
35             if(g[cur][j] > MOD) g[cur][j] %= MOD;
36             if(g[cur][j] < 0) g[cur][j] = (g[cur][j] % MOD) + MOD;
37         }
38     }
39     printf("%d\\n%d\\n", f[cur][nb], g[cur][nb]);  
40     return 0;  
41 }

参考1:http://blog.csdn.net/moep0/article/details/52760974

参考2:http://blog.csdn.net/litble/article/details/67640655

 

算法分析:

第一个问题可以参考最长公共子序列原题的题解。

 第二个问题可以阅读参考1参考2的分析和代码自己理解。

这里摘抄参考1里面的两段代码留存:

代码一:使用了滚动数组。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <stack>
 6 #include <vector>
 7 #include <queue>
 8 #include <cstring>
 9 #include <string>
10 #include <map>
11 #include <set>
12 using namespace std;
13  
14 const int BufferSize = 1 << 16;
15 char buffer[BufferSize], *Head, *Tail;
16 inline char Getchar() {
17     if(Head == Tail) {
18         int l = fread(buffer, 1, BufferSize, stdin);
19         Tail = (Head = buffer) + l;
20     }
21     return *Head++;
22 }
23 int read() {
24     int x = 0, f = 1; char c = Getchar();
25     while(!isdigit(c)){ if(c == \'-\') f = -1; c = Getchar(); }
26     while(isdigit(c)){ x = x * 10 + c - \'0\'; c = Getchar(); }
27     return x * f;
28 }
29  
30 #define maxn 5010
31 #define MOD 100000000
32 char A[maxn], B[maxn], cur;
33 int f[2][maxn], g[2][maxn];
34  
35 int main() {
36     scanf("%s%s", A + 1, B + 1);
37     int na = strlen(A + 1), nb = strlen(B + 1);
38     A[na--] = \'\\0\'; B[nb--] = \'\\0\';
39      
40     for(int i = 1; i <= nb; i++) g[0][i] = 1; g[0][0] = g[1][0] = 1;
41     for(int i = 1; i <= na; i++) {
42         cur ^= 1;
43         for(int j = 1; j <= nb; j++) {
44             f[cur][j] = max(f[cur^1][j], f[cur][j-1]);
45             if(A[i] == B[j]) f[cur][j] = max(f[cur][j], f[cur^1][j-1] + 1);
46             g[cur][j] = 0;
47             if(f[cur][j] == f[cur^1][j]) g[cur][j] += g[cur^1][j];
48             if(f[cur][j] == f[cur][j-1]) g[cur][j] += g[cur][j-1];
49             if(f[cur][j] == f[cur^1][j] && f[cur][j] == f[cur][j-1] && f[cur^1][j-1] == f[cur][j]) g[cur][j] -= g[cur^1][j-1];
50             if(A[i] == B[j] && f[cur][j] == f[cur^1][j-1] + 1) g[cur][j] += g[cur^1][j-1];
51             if(g[cur][j] > MOD) g[cur][j] %= MOD;
52             if(g[cur][j] < 0) g[cur][j] = (g[cur][j] % MOD) + MOD;
53         }
54     }
55      
56     printf("%d\\n%d\\n", f[cur][nb], g[cur][nb]);
57      
58     return 0;
59 }
View Code

代码二:不使用滚动数组,假如测试数据较小,可以AC。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #define mod 100000000
 7 using namespace std;
 8 string a,b;
 9 int f[5005][5005],g[5005][5005];
10 int main(){
11     cin>>a>>b;
12     int l1=a.length()-1,l2=b.length()-1;
13     a=\' \'+a,b=\' \'+b;
14     for(int i=0;i<=l1;i++)g[i][0]=1;
15     for(int i=0;i<=l2;i++)g[0][i]=1;
16     for(int i=1;i<=l1;i++)
17       for(int j=1;j<=l2;j++)
18         {
19               if(a[i]==b[j])
20               {
21                   f[i][j]=f[i-1][j-1]+1;
22                 g[i][j]=g[i-1][j-1];
23                 if(f[i][j]==f[i][j-1])g[i][j]=(g[i][j]+g[i][j-1])%mod;
24                 if(f[i][j]==f[i-1][j])g[i][j]=(g[i][j]+g[i-1][j])%mod;    
25             }
26               else 
27               {
28                   f[i][j]=max(f[i-1][j],f[i][j-1]);
29                   if(f[i][j]==f[i-1][j])g[i][j]=(g[i][j]+g[i-1][j])%mod;
30                 if(f[i][j]==f[i][j-1])g[i][j]=(g[i][j]+g[i][j-1])%mod;
31                 if(f[i][j]==f[i-1][j-1])g[i][j]-=g[i-1][j-1],g[i][j]=(g[i][j]+mod)%mod;
32             }
33         }
34     cout<<f[l1][l2]<<endl<<g[l1][l2]%mod;
35     return 0;
36 }
View Code

 

以上是关于MATLAB 最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章

动态规划 最长公共子序列 过程图解

最长公共子序列的应用

C语言实现最长公共子串与最长公共子序列

最长递增子序列 && 最大子序列最长递增子序列最长公共子串最长公共子序列字符串编辑距离

codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)

最长公共子串和最长公共子序列