动态规划--最长公共子串

两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。其实这又是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab")

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  1

a  0  1  0
我们看矩阵的斜对角线最长的那个就能找出最长公共子串。
不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。
   b  a  b

c  0  0  0

a  0  1  0

b  1  0  2

a  0  2  0

这样矩阵中的最大元素就是 最长公共子串的长度。

import java.util.Scanner;

public class LCS {
 
    public static void main(String[] args) {
         
    	 Scanner in=new Scanner(System.in);
  	     String s1=in.nextLine();
  	     String s2=in.nextLine();
  	     System.out.println(iQueryMaxCommString(s1,s2));
       
       
    }
    
    public static String iQueryMaxCommString(String stringA, String stringB)
    {
        /* 在这里实现功能,将结果填入输入数组中*/ 
    	
    	 //String x = "wer";
         //String y = "werasdfaswer";
    	  String x=stringA;
    	  String y=stringB;
         // 设置字符串长度
         int substringLength1 = x.length();
         int substringLength2 = y.length(); // 具体大小可自行设置
  
         // 构造二维数组记录子问题x[i]和y[i]的LCS的长度
         int[][] opt = new int[substringLength1 + 1][substringLength2 + 1];
  
         // 动态规划计算所有子问题。也可从前到后。
         for (int i =0; i <substringLength1; i++) {
             for (int j = 0; j <substringLength2 ; j++) {
                 if (x.charAt(i) == y.charAt(j))
                 	if(i==0||j==0){
                 		opt[i][j]=1;
                 	}
                 	else{
                 		opt[i][j] = opt[i -1][j - 1] + 1;//左上角加1
                 	}                                 
             }
         }
         
         /*System.out.println("substring1:" + x);
         System.out.println("substring2:" + y);
         System.out.println("LCS:");
         //输出状态矩阵
         for (int i =0; i <substringLength1; i++) {
             for (int j = 0; j <substringLength2 ; j++) {              
                System.out.print(opt[i][j]+" ");                             
             }
             System.out.println();
         }
         */
         //找到状态举矩阵的最大值,和坐标indexi,indexj 
         int max=opt[0][0];
         int indexi=0,indexj=0;
         for (int i =0; i <substringLength1; i++) {
             for (int j = 0; j <substringLength2 ; j++) {              
             	if(opt[i][j] >max){
             		max=opt[i][j];     
             		indexi=i;
             		indexj=j;
             	}
             }           
         }
         //System.out.println(max);
         if(max!=0){       
         //取短的字符串输出
        String rs=null;
         int indexofmax=0,shortlen;
         if(substringLength1>substringLength2){
         	shortlen=substringLength2;
         	rs=y;
         	indexofmax=indexj;
         }
         else{
         	shortlen=substringLength1;
         	rs=x;
         	indexofmax=indexi;
         }
         StringBuffer sb=new StringBuffer();
         for(int i=0;i<max;i++){
         	sb.append(rs.charAt(indexofmax-max+1+i)); 
         }
           return sb.toString();
         }
         return null;
       
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值