最短超级串

描述:给定一个字符串数组 A,找到以 A 中每个字符串作为子字符串的最短字符串。
package com.zxj.algorithm.动态规划.字符串;

import lombok.extern.slf4j.Slf4j;
import lombok.var;

import java.util.Arrays;

/**
 * 描述:给定一个字符串数组 A,找到以 A 中每个字符串作为子字符串的最短字符串。
 */
@Slf4j
public class 最短超级串 {
    //data[i][j] 第i个和第j个字符串,以s1最后一个字符结尾的最长公共子串长度
    static int[][] data;
    //
    static String[] S;

    /**
     * 输入:["alex","loves","lintcode"]
     * 输出:"
     * alexloveslintcode"
     * alexloveslintcode
     *
     * 

* 输入:["catg","ctaagt","gcta","ttca","atgcatc"] * 输出: * gctaagttcatgcatc" * gctaagttcatgcatc */ public static void main(String[] args) { // S = new String[]{"catg", "ctaagt", "gcta", "ttca", "atgcatc"}; S = new String[]{"alex", "loves", "lintcode"}; int n = S.length; data = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) { data[i][j] = -1; } else { data[i][j] = getLen(S[i], S[j]); } } } for (var d : data) { log.info(Arrays.toString(d)); } log.info(""); long startTs = System.currentTimeMillis(); String memos = dynamicProgramAlgorithm(n); log.info("{}, ts={}", memos, System.currentTimeMillis() - startTs); } public static String dynamicProgramAlgorithm(int size) { if (size == 0) { return ""; } int[][] dataTemp = new int[size][size]; for (int i = 0; i < dataTemp.length; i++) { dataTemp[i] = Arrays.copyOf(data[i], data[i].length); } //相邻规则 int[] sorts = new int[size]; Arrays.fill(sorts, -1); int n = size - 1; int maxLen = -1; while (n > 0) { //查询最大一个值 int maxI = 0; int maxJ = 0; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (dataTemp[i][j] > maxLen) { maxI = i; maxJ = j; maxLen = dataTemp[i][j]; } } } //排序规则 sorts[maxI] = maxJ; //初始化 dataTemp[maxJ][maxI] = -1; for (int k = 0; k < size; k++) { dataTemp[maxI][k] = -1; dataTemp[k][maxJ] = -1; } maxLen = -1; n--; } log.info("相邻规则:{}", Arrays.toString(sorts)); //排序规则 int[] resultSorts = new int[size]; Arrays.fill(resultSorts, -1); for (int i = 0; i < sorts.length; i++) { if (sorts[i] == -1) { resultSorts[size - 1] = i; } } for (int i = size - 2; i >= 0; i--) { for (int j = 0; j < size; j++) { if (sorts[j] == resultSorts[i + 1]) { resultSorts[i] = j; } } } log.info("排序规则:{}", Arrays.toString(resultSorts)); String resultStr = S[resultSorts[0]]; for (int i = 1; i < resultSorts.length; i++) { int lastIndex = resultSorts[i - 1]; int currentIndex = resultSorts[i]; int publicLength = data[lastIndex][currentIndex]; resultStr = resultStr + S[currentIndex].substring(publicLength); log.info("i={}, last={}, current={}, pubLen={}, str={}", i, lastIndex, currentIndex, publicLength, resultStr); } return resultStr; } /** * @param s1 字符串1 * @param s2 字符串2 * @return 以s1最后一个字符结尾的最长公共子串长度 */ public static int getLen(String s1, String s2) { if (s1 == null || s2 == null) { return 0; } int[][] data = new int[s1.length()][s2.length()]; int maxLen = 0; char[] a1 = s1.toCharArray(); char[] a2 = s2.toCharArray(); for (int i = 0; i < s1.length(); i++) { for (int j = 0; j < s2.length(); j++) { if (a1[i] == a2[j]) { int len; if (i == 0 || j == 0) { len = 1; } else { len = data[i - 1][j - 1] + 1; } data[i][j] = len; //以s1最后一个字符结尾的公共子串长度 if (i == s1.length() - 1 && len == j + 1) { maxLen = Math.max(maxLen, len); } } } } return maxLen; } }

测试用例1:

 

{"alex", "loves", "lintcode"}

输出:

alexloveslintcode

测试用例2:

 

{"catg", "ctaagt", "gcta", "ttca", "atgcatc"}

输出:

gctaagttcatgcatc

你可能感兴趣的:(#,动态规划,算法,动态规划)