【华为机试065】查找两个字符串的最长公共子串

题目描述:

查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。

Java实现:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String str1 = sc.nextLine();

            String str2 = sc.nextLine();

            if (str1.length() > str2.length()) {
                System.out.println(getMaxComSubStr2(str2, str1));
            } else {
                System.out.println(getMaxComSubStr2(str1, str2));
            }
        }
    }
//穷举法
    private static  String getMaxComSubStr(String str1, String str2) {
       int maxLength = 0;

       int start = 0;
       int end = 0;
       for (int i = 0; i < str1.length(); i++) {
           for (int j = i+1; j <= str1.length(); j++) {
               if (str2.contains(str1.substring(i, j)) && (j-i) > maxLength) {
                   maxLength = j - i;
                   start = i;
                   end = j;
               }
           }
        }
        return str1.substring(start, end);
}

//动态规划法
    private static int[][] getdp(char[] chars1, char[] chars2) {
        int[][] dp = new int[chars1.length][chars2.length];
        //第一列
        for (int i = 0; i < chars1.length; i++) {
            if (chars1[i] == chars2[0])
                dp[i][0] = 1;
        }
        //第一行
        for (int j = 0; j < chars2.length; j++) {
            if (chars1[0] == chars2[j])
                dp[0][j] = 1;
        }

        for (int i = 1; i < chars1.length; i++) {
            for (int j = 1; j < chars2.length; j++) {
                if (chars1[i] == chars2[j]) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
            }
        }
        return dp;
    }

    private static String getMaxComSubStr2(String str1, String str2) {
        char[] chars1 = str1.toCharArray();
        char[] chars2 = str2.toCharArray();
        int[][] dp = getdp(chars1, chars2);
        int end = 0;
        int max = 0;
        for (int i = 0; i < chars1.length; i++) {
            for (int j = 0; j < chars2.length; j++) {
                if (max < dp[i][j]) {
                    max = dp[i][j];
                    end = i;
                }
            }
        }
        return str1.substring(end+1-max, end+1);
    }
}

关键点:

  • 穷举法是遍历较短字符串的所有子串,判断较长字符串是否包含
  • 动态规划法的关键是找出状态转移方程

猜你喜欢

转载自blog.csdn.net/heyiamcoming/article/details/81100388