对于最长公共子序列的理解。

news/2024/7/3 20:27:12

 解决LCS问题,需要把原问题分解成若干个子问题,所以需要刻画LCS的特征。

       设A=“a0,a1,…,am”,B=“b0,b1,…,bn”,且Z=“z0,z1,…,zk”为它们的最长公共子序列。不难证明有以下性质:
       如果am=bn,则zk=am=bn,且“z0,z1,…,z(k-1)”是“a0,a1,…,a(m-1)”和“b0,b1,…,b(n-1)”的一个最长公共子序列;
       如果am!=bn,则若zk!=am,蕴涵“z0,z1,…,zk”是“a0,a1,…,a(m-1)”和“b0,b1,…,bn”的一个最长公共子序列;
       如果am!=bn,则若zk!=bn,蕴涵“z0,z1,…,zk”是“a0,a1,…,am”和“b0,b1,…,b(n-1)”的一个最长公共子序列。

       

感谢这个博主,这意思是,求最长公共子序列,你肯定要比较A字串M个和B字串N个中的元素是否相同,那怎么记录呢,就想到用二维数组,但是你不能记录每一个是否相同吧,记为0和1的话太没用了,那怎么办,利用动态规划,前面比较过的,你可以拿来用啊,这就用到了递归思想,意思就是每次只比较A的B的最后一个,如果相同,则+1,并且记录寻找的路径,如果不同,就寻找减去最后一个元素的两种谁的公共子序列比较长,就选谁(比如呢,A的最后一个是不是没用了,那就比较A减去倒数第一个和B进行比较,但是还可能B在增长,那么就是B减去倒数第一个)在这里,我用二维数组c存有多少个公共子序列,b存寻找的方向,1代表斜着,2代表向上边,3代表左边

我们可以发现,假设我需要求 a1 ... am 和 b1 .. b(n-1)的LCS 和 a1 ... a(m-1) 和 b1 .. bn的LCS,一定会递归地并且重复地把如a1... a(m-1) 与 b1 ... b(n-1) 的 LCS 计算几次。所以我们需要一个数据结构来记录中间结果,避免重复计算。

        假设我们用c[i,j]表示Xi 和 Yj 的LCS的长度(直接保存最长公共子序列的中间结果不现实,需要先借助LCS的长度)。其中X = {x1 ... xm},Y ={y1...yn},Xi = {x1 ... xi},Yj={y1... yj}。可得递归公式如下:

借用  https://blog.csdn.net/hrn1216/article/details/51534607 博主的图。

借用博主的图来说明

初始化为0,你发现这样,对于(1.1)就是1和3的比较,对于(1.2)就是A(1),B(3.5)的比较,然后依次,发现都为0,B依次增长,然后A增长,(2.1)就是A(1.3) B(3)的比较,诶,出现了,就是如图记录为坐标(2-1,1-0)的值+1,放入到(2.1)中,这意味着什么呢,就是A,B串各减去一,只留各自最后一个作比较,好了,如图

然后就是B递增,(2.2)就是A(1.3)和B(3.5)发现3和5不同,那就max吧,看是A减去最后一个的子串和B比较得出的公共子序列长呢还是B减去最后一个子串和A比较的公共子序列长呢。发现是(2.1)=1比较长,也就是A(1.3)和B(3),然后顺延咯

最后得出如图

OK,下面贴出实现这个表格的代码

void LCSLength(int m, int n, char *x, char *y, int (*c)[15], int (*b)[15])
{
    int i, j;
    for (int i = 0; i <= m+1; i++) c[i][0] = 0;
    for (int i = 0; i <= n+1; i++) c[0][i] = 0;
    for (int i = 1; i<m+1; i++)
        for (int j = 1; j <= n+1; 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; }
        }
}

初始化,然后遍历m*n的列表,

{

如果A和B串最后一个比较相同,+1

不然{

要么c(i-1,j)>c(i,j-1),则延续上边

}

不然{

要么c(i,j-1)>c(i-1,j),则延续左边

}

}

下面贴出寻找的代码,寻找是倒着寻找的,从二维数组的最后一个,到第(0.0),只有出现1,也就是很明显的A和B的最后一个相等,才会输出嘛,不然就意味这这俩不等,是延续上面的嘛。

void LCS(int i,int j, char *x, int (*b)[15])
{
    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);
}

OK,下面就是主函数了,不做说明了,C++学得不好

int main()
{
    cout << "请输入序列的长度" << endl;
    int m, n;
    cin >> m >> n;
    cout << "请输入公共子序列一" << endl;
    char x[100], y[100];
    for (int i = 1; i <= m; i++)
    {
        cin >> x[i];
        cout << x[i];
    }
    
    for (int j = 1; j <= n; j++)
        cin >> y[j];
    int c[15][15];
    int b[15][15];
    LCSLength(m, n, x, y, c,b);
    for (int i = 0; i < m+1; i++) {
        for (int j = 0; j < n+1; j++)
        {
            cout << c[i][j] << " ";
        }
        cout << endl;
    }
    LCS(m, n, x, b);
    system("pause");
}

 

转载于:https://www.cnblogs.com/czrb/p/9141016.html


http://www.niftyadmin.cn/n/3142477.html

相关文章

函数编程

1. 编码问题 i.请说明python2与python3中的默认编码是什么&#xff1f; python2 ASCII 码 python3 字符串为unicode&#xff0c;文件默认编码为utf-8 ii.为什么会出现中文乱码&#xff1f;你能列举出现乱码的情况有哪几种&#xff1f; 读取使用的编码和存储时使用的编码不一致…

苏州大学新生寒假训练day3 D - Bone Collector

苏州大学新生寒假训练day3 D - Bone Collector Problem: Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … The bone colle…

用python算圆周率及进度条提示

&#xff08;一&#xff09;圆周率 &#xff1a; &#xff08;1&#xff09;圆周率是指平面上圆的周长与直径之比 &#xff08;ratio of the circumference of a circle to the diameter&#xff09; 。用符号π表示。中国古代有圆率、圆率、周等名称。 &#xff08;2&#xf…

【Kubernetes】kube-dns 持续重启

kuberbetes部署和启动正常&#xff0c;但是kube-dns持续重启 使用命令 kubectl get pods --all-namespaces 得到结果 从图中可以看出kube-dns-c7d85897f-jmntw 在不断重启 使用命令 kubectl describe pod kube-dns-c7d85897f-jmntw -n kube-system 得到结果 Name: ku…

BJTU1820 懒羊羊的作业

BJTU1820 懒羊羊的作业 题目&#xff1a; 看过国产动画片的同学都知道&#xff0c;懒羊羊是一只非常懒的羊&#xff0c;整天除了吃就是睡&#xff0c;根本没有时间做作业。明天就是周一了&#xff0c;村长慢羊羊留的作业&#xff1a; 把 &#x1d45b; n 个整数从大到小排序…

计算分段函数

1、计算f(x)的值&#xff1a;输入x&#xff0c;计算并输出下列分段函数f(x)的值&#xff08;保留1位小数&#xff09;。试编写相应程序。 Yf(x)1/x (当x!0) Yf(x)0 (当x0) #include<stdio.h> int main(void){ float x,y; printf("Enter x:\n"); scanf("%f…

dataframe初始化

转载于:https://www.cnblogs.com/bafenqingnian/p/9152547.html

洛谷题解: P1130 红牌

洛谷题解&#xff1a; P1130 红牌 题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂 &#xff0c;一共包括NNN个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程&#xff0c;每一步政府都派了MMM…