经典算法之动态规划--求最大公共子序列

作为新人,之前对C,C++了解的比较少,关于算法方面更是一窍不通,但最近却痴迷上了算法,哪怕是前辈们不屑一顾的东东,我弄明白了后都会欣喜若狂!

今天将遇到的问题和java实现贴出来和同为新人的博友分享,老鸟可以可以直接关网页了。

定义:

  子序列:一个给定序列的子序列是再该序列中删去若干元素后得到的序列。即:给定{x1,x2,...,xm}和Z={z1,z2,...,zk},X的子序列是指存在一个严格递增下表序列{i1,i2,...ik}

      使得对所有的j=1,2,...k,都有zj=xij。例如:Z={b,d,c,a}是X={a,b,c,d,c,b,a}的一个子序列

公共子序列:如果Z是序列X的子序列,又是序列Y的子序列,则称Z是序列X和序列Y的公共子序列。例如:序列“bcba” 是"abcbdab"和“bdcaba”的公共子序列

问题:

  给定两个序列X={x1,x2,...xm}和Y={y1,y2,...,yn},找出序列X,Y的最长公共子序列。

思路: f(i,j)表示第一个序列的第i元素后的最大子序列及第二个序列的第j元素后的最大子序列的公共子序列长度

如果i=1,j=1,且有x1=y1,那么f(1,1)=f(2,2)+1;

同理:xi == xj , 那么f(i,j)=f(i+1,j+1)+1;

如果 xi != xj , 那么f(i,j)=Max(f(i,j+1) , f(i+1,j));

这样,当i=x.length 或 j=y.length 时,越界,值为0;

我们已经找到了最优值了,如何获取这个最优解呢?

我们可以用个二维数组boolean [][]s 来记录在寻找最优值时xi和yj的比较结果,相等true, 否则false;

如果i=0,j=0, s[0][0]=true,且f(i,j)=f(0,0),那么x[0]就是最优解的第一个元素,

同理,如果s[i][j]=true,且f(i,j)=f(0,0)-w  ,  (其中w 从0开始,每确定公共序列中的一项时,w+1);

over!

java代码如下:

//动态规划
//求最大公共子序列
public class Demo7 {
    public static void main(String[]args){
        String a ="abcdefghi";
        String b ="efghiabcd";
        GetBest(a.toCharArray(),b.toCharArray(),a.length(),b.length());
    }
    public static void GetBest(char[]x,char[]y,int m,int n){
        boolean[][] s=new boolean[x.length][y.length];
        getMax(x,y,0,0,s);
        for(int t=0,w=0,i=0;i<m;i++){
            for(int j=t;j<n;j++){
                if(s[i][j]==true&&getMax(x,y,i,j,s)==getMax(x,y,0,0,s)-w){
                    System.out.print(x[i]+" ");
                    w++;
                    t=j+1;
                    break;
                }
            }
        }
    }

    public static  int getMax(char[]x,char[]y,int m,int n,boolean[][] s){
        if(m==x.length||n==y.length){
            return 0;
        }
        if(x[m]==y[n]){
            s[m][n]=true;
            return getMax(x,y,m+1,n+1,s)+1;
        }else{
            s[m][n]=false;
            if(getMax(x,y,m,n+1,s)>getMax(x,y,m+1,n,s)){
                return getMax(x,y,m,n+1,s);
            }else{
                return getMax(x,y,m+1,n,s);
            }
        }
    }
}

 

经典算法之动态规划--求最大公共子序列

时间: 2024-10-03 14:56:14

经典算法之动态规划--求最大公共子序列的相关文章

经典算法宝典——动态规划思想(六)(2)

1.01背包问题 有N件物品和一个容量为V的背包,第i件物品的体积是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 解析: 这是最基础的背包问题,特点是每种物品仅有一件,可以选择放或不放.用子问题定义状态,即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值.其状态转移方程便是f[i][v] = max{f[i-1][v], f[i-1][v-c[i]]+w[i]},这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的,所以有必要将它详细解

spoj Longest Common Substring (多串求最大公共子序列)

题目链接: https://vjudge.net/problem/SPOJ-LCS 题意: 最多10行字符串 求最大公共子序列 数据范围: $1\leq |S| \leq100000$ 分析: 让他们都和第一个字符串匹配,算出每个字符串与第一个字符串的,以$i$位置(i指的是在s1中的位置)结尾匹配的最大长度 与其它字符串的匹配取最小值 最后对所有位置取最大值 超时代码:(题限是236ms,这个代码跑2000ms没问题) #include<bits/stdc++.h> #define ll l

动态规划(最大公共子序列)

网上关于动态规划的资料很多,看了很多,总结如下: 求原字符串和其反串的最大公共子序列(不是子串,因为可以不连续)的长度(使用动态规划很容易求得) 1)首先是要知道最长公共子序列的长度的动态规划方程 设有字符串a[0...n],b[0...m],下面就是递推公式.字符串a对应的是二维数组num的行,字符串b对应的是二维数组num的列. 2.其次要看的懂求BDCABA与ABCBDAB的最大公共子序列 3.关键代码如下: 1 package com.sxt.bean; 2 3 import java.

算法题:求一个序列S中所有包含T的子序列(distinct sub sequence)

题: 给定一个序列S以及它的一个子序列T,求S的所有包含T的子序列.例: S = [1, 2, 3, 2, 4] T = [1, 2, 4] 则S的所有包含T的子序列为: [1, 2, 3, 2, 4] [1, 2, 3, 4] [1, 2, 2, 4] [1, 2, 4] 解: 首先可以拆解为两个问题: 1. 求S的所有子序列:其中又涉及到去重的问题. 2. 求S的所有子序列中包含T的子序列. 暂时先不考虑去重,看看问题1怎么解: 一.求S的子序列 单纯求一个序列的所有子序列的话,就是求序列的

五大经典算法之动态规划

一.概念起源 ??动态规划,又名DP算法(取自其Dynamic Programming的缩写),最初是运筹学的一个分支,是用来求解决策过程最优化的数学方法. 二.基本思想 ??把 多阶段过程 转化为一系列单阶段过程,利用各阶段之间的关系,逐个求解.那什么叫多阶段过程呢? 多阶段过程:首先大家可以思考一下以下这个问题: 假如我们有面值为1元/3元/5元的硬币若干枚,如何用最少的硬币凑够137元? 当然我们可以使用暴力枚举解决这个问题,不够那样复杂度就太高了.我们可以这样考虑,凑齐137元可以看成一

经典算法之动态规划

动态规划让我纠结了好一阵子,背包问题让我觉得不知道怎么入手,到处搜索都是一条条的公式,晦涩难懂.偶然间发现了一个博客写的动态规划解释非常的好,虽然还没完全随心所用,但是总算是入门了,下列内容为转载,附上原地址:http://www.cnblogs.com/sdjl/articles/1274312.html 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动

[经典算法] Eratosthenes筛选求质数

题目说明: 除了自身之外,无法被其它整数整除的数称之为质数,要求质数很简单,但如何快速的求出质数则一直是程式设计人员与数学家努力的课题,在这边介绍一个著名的 Eratosthenes求质数方法. 题目解析: 首先知道这个问题可以使用回圈来求解,将一个指定的数除以所有小于它的数,若可以整除就不是质数,然而如何减少回圈的检查次数?如何求出小于N的所有质数?首先假设要检查的数是N好了,则事实上只要检查至N的开根号就可以了,道理很简单,假设A*B = N,如果A大于N的开根号,则事实上在小于A之前的检查

HDU 1159 Common Subsequence 最大公共子序列

Problem Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a stri

ACM最大公共子序列&amp;&amp;回文串

---恢复内容开始--- Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be in