zoukankan      html  css  js  c++  java
  • 943.Find the Shortest Superstring --- 旅行商问题&状态压缩DP

    943.Find the Shortest Superstring

    Given an array A of strings, find any smallest string that contains each string in A as a substring.

    We may assume that no string in A is substring of another string in A.

    Example 1:

    Input: ["alex","loves","leetcode"]

    Output: "alexlovesleetcode"

    Explanation: All permutations of "alex","loves","leetcode" would also be accepted.

    2019.1.19算法群里的题目:这道题涉及到旅行商问题,解法是状态压缩dp

    参考大神的解法,梳理了下解法;

    题意

    给一个字符串序列,找到包含序列中所有字符串的最小的字符串

    分析

    • (1)先建图:预处理计算出Cost,也就是一个节点到另一个节点的权重,这里的话,,g[i][j]表示将A[j]加到A[i]的后面,路径的长度:

    • (2) 题目转化为找一条访问过每个节点一次的最短的路径

    • (3) 记忆化DP:

      • dp[s][i] :表示访问了节点集合s,且最后一个节点是i的最短的路径,注意这里s是一个Binary String,表示哪些节点已经访问过了,为1的节点是已经访问过的;

      Assume we want to travel nodes: {n1, n2, n3, n4} then
      i = 2 ^ n1 +2 ^ n2 +2 ^ n3 +2 ^ n4;

      • path[s][i]:表示访问了节点集合s,并且最后一个节点是i,i前面的一个节点; 记录路径中,i的前面的一个点,以便于重建途径的时候的回溯
    • (4) dp更新策略:
      dp[s][i] = min(dp[s - 2^i][j] + g[j][i]) #将j加到i的后面

    代码

    /**
    题意:给一个字符串序列,找到包含序列中所有字符串的最小的子串
    分析:
    */
    
    class Solution {
        public String shortestSuperstring(String[] A) {
            int n = A.length;
            int[][] graph = new int[n][n];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    graph[i][j] = calCost(A, i, j);  //把j加到i后面的路径长度,即图中i->j的边长
                    graph[j][i] = calCost(A, j, i);
                }
            }
            
            int[][] dp = new int[1 << n][n];  //dp[s][i] :表示访问了节点集合s,且最后一个节点是i的最短的路径
            int[][] path = new int[1 << n][n];
            int min = Integer.MAX_VALUE, last = -1;
            
            for (int state = 1; state < (1 << n); state++) {  //枚举所有的节点集合组成状态
                Arrays.fill(dp[state], Integer.MAX_VALUE);
                for (int node = 0; node < n; node++) {
                    if ((state & (1 << node)) > 0) { //判断node在不在节点集合中
                        int leftState = state - (1 << node);  //剩下的节点集合
                        if (leftState == 0) {  //如果只剩一个节点了,则当前长度就是node的长度
                            dp[state][node] = A[node].length();
                        } else {
                            for (int k = 0; k < n; k++) {  //dp更新
                                if (dp[leftState][k] != Integer.MAX_VALUE && 
                                    dp[leftState][k] + graph[k][node] < dp[state][node]) {  //如果访问过了leftState且经过k点的路径更小,则更
                                    dp[state][node] = dp[leftState][k] + graph[k][node];
                                    path[state][node] = k;
                                }
                            }
                        }
                    }
                    if (state == (1 << n) - 1 && dp[state][node] < min) {
                        min = dp[state][node];
                        last = node;
                    }
                    //System.out.println(dp[state][node]);
                }
            }
            //建立路径        
            StringBuilder sb = new StringBuilder();
            int cur = (1 << n) - 1;
            Stack<Integer> stack = new Stack<>();
            while (cur > 0) {
                stack.push(last);
                int temp = cur;
                cur -= (1 << last);
                last = path[temp][last];
            }
    		        
            int i = stack.pop();
            sb.append(A[i]);
            while (!stack.isEmpty()) {
                int j = stack.pop();
                sb.append(A[j].substring(A[j].length() - graph[i][j]));
                i = j;
            }
            return sb.toString();
        }
        
        private int calCost(String[] A, int i, int j) {
            for (int pos = 1; pos < A[i].length(); pos++) {
                if (A[j].startsWith(A[i].substring(pos))) {
                    return A[j].length() - A[i].length() + pos;
                }
            }
            return A[j].length();
        }
    }
    
    
  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/shawshawwan/p/10291893.html
Copyright © 2011-2022 走看看