最长公共子序列


题目要求:
    第一行给出一个整数N(0<N<100)表示待测数据。接下来魅族数据两行,分别为待测的两组字符串,每个字符串长度不大于1000.

输出要求:每组测试数据输出一个整数,表示最长公共子序列长度,每组结果占一行。


样例输入:

2
asdf
adfsd
123abc
abc123abc

样例输出:

3
6

这道题是一道经典的动态规划:

首先推出这个题的动态方程:


我来解释一下上面这个方程:

    设arr[i][j]表示 (a1,a2,a3,.....,ai) 与 (b1,b2,b3,...,bj)子串的最长子序列的长度。

    1.当 i = 0, j = 0时,两个子串都为空,那么公共子序列当然就为空。

    2.当i , j>0 而且 a1 = bj 时,假如说现在比较的是(a的前i个(a1,a2,a3,...,ai)和b的前j个(b1,b2,b3,...,bj))的最长公共子序列,如果a[i]和b[j]相等  那么一目了然,这个问题就可以变成(a的前i-1个(a1,a2,a3,...,ai-1)和b的前j-1个(b1,b2,b3,...,bj-1))的最长公共子序列 + 1。

    3.当 i , j>0而且 ai!=bj 时,如果不符合上面那种情况(就是 a[i]!=b[j] )那么就不可能应用  arr[i][j]=arr[i-1][j-1]+1  递推公式, 因为你+1其实就加的是 最后a[i]=a[j]这一项来更新 最长公共子序列的长度值
    然后就分为两种情况( arr[i-1][j] > arr[i][j-1] 或者 arr[i-1][j] < arr[i][j-1] ):
      1>.最长公共序列可以在(a1,a2,....a(n-1))和 (b1,b2,...bn)中找。

      2>.最长公共序列可以在(a1,a2,....an) 和 (b1,b2,...b(n-1))中找。


那么就将arr[i][j]的值赋值为arr[i-1][j]与arr[i][j-1]中的最大值即可。

最后取arr[a.length()][b.length()]对应的值即是答案。


代码如下:

[java]  view plain  copy
  1. import java.util.Scanner;  
  2. public class Main {  
  3.     public static void main(String[] args){  
  4.           
  5.         Scanner in = new Scanner(System.in);  
  6.           
  7.         int time = 0;  
  8.         time = in.nextInt();  
  9.         String a = null;  
  10.         String b = null;  
  11.           
  12.         while( time-- != 0){  
  13.             a=in.next();  
  14.             b=in.next();  
  15.             System.out.println(sub(a,b));  
  16.         }  
  17.           
  18.     }  
  19.     public static int sub(String a,String b){  
  20.         int[][] arr = new int[a.length()+1][b.length()+1]; //   初始化递推数组  
  21.         //这个数组表示 a字符串前n位 与  b字符串前k位   的最长公共子序列长度  int[][] arr = new int[n][k];  
  22.         for(int i=0;i<a.length();i++){  
  23.             arr[i][0] = 0;  //初始化递推数组  a数组的(0-i)子串和b数组的(0-0)子串 公共部分当然是0   
  24.         }  
  25.         for(int j=0;j<b.length();j++){  
  26.             arr[0][j] = 0;  //初始化递推数组  b数组的(0-i)子串和a数组的(0-0)子串 公共部分当然也是0  
  27.         }  
  28.         //上面也就是第一种情况  
  29.         for(int i=1;i<=a.length();i++){  
  30.             for(int j=1;j<=b.length();j++){  
  31.                 if(a.charAt(i-1)==b.charAt(j-1)){   
  32.                     arr[i][j] = arr[i-1][j-1]+1//对应第二种情况   
  33.                 }  
  34.                 else if(arr[i-1][j] > arr[i][j-1]){  
  35.                     arr[i][j] = arr[i-1][j]; //对应第三种情况  这是递推式 一行一行算的 先第一行 所以 arr[i-1][j] 不会为空  
  36.                 }  
  37.                 else{  
  38.                     arr[i][j] = arr[i][j-1]; //对应第三种情况   arr[i][j-1]也算过了 也不会为空  
  39.                 }  
  40.                   
  41.             }  
  42.         }  
  43.         return arr[a.length()][b.length()];  
  44.     }  
  45.   
  46. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值