<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hamiltonian path Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/hamiltonian-path/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/hamiltonian-path/</link>
	<description></description>
	<lastBuildDate>Thu, 30 Jan 2020 05:14:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>Hamiltonian path Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/hamiltonian-path/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 996. Number of Squareful Arrays</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-996-number-of-squareful-arrays/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-996-number-of-squareful-arrays/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 17 Feb 2019 09:02:43 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[Hamiltonian path]]></category>
		<category><![CDATA[search]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4871</guid>

					<description><![CDATA[<p>Given an array&#160;A&#160;of non-negative integers, the array is&#160;squareful&#160;if for every pair of adjacent elements, their sum is a perfect square. Return the number of permutations&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-996-number-of-squareful-arrays/">花花酱 LeetCode 996. Number of Squareful Arrays</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode Weekly Contest 124 (993, 994, 995, 996) - 刷题找工作" width="500" height="375" src="https://www.youtube.com/embed/ISnktonx7rY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Given an array&nbsp;<code>A</code>&nbsp;of non-negative integers, the array is&nbsp;<em>squareful</em>&nbsp;if for every pair of adjacent elements, their sum is a perfect square.</p>



<p>Return the number of permutations of A that are squareful.&nbsp; Two permutations&nbsp;<code>A1</code>&nbsp;and&nbsp;<code>A2</code>&nbsp;differ if and only if there is some index&nbsp;<code>i</code>&nbsp;such that&nbsp;<code>A1[i] != A2[i]</code>.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>[1,17,8]
<strong>Output: </strong>2
<strong>Explanation: </strong>
[1,8,17] and [17,8,1] are the valid permutations.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>[2,2,2]
<strong>Output: </strong>1
</pre>



<p><strong>Note:</strong></p>



<ol><li><code>1 &lt;= A.length &lt;= 12</code></li><li><code>0 &lt;= A[i] &lt;= 1e9</code></li></ol>



<h2><strong>Solution1:&nbsp;DFS</strong></h2>



<p>Try all permutations with pruning.</p>



<p>Time complexity: O(n!)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, running time: 4 ms, 8.8 MB
class Solution {
public:
  int numSquarefulPerms(vector&lt;int&gt;&amp; A) {
    std::sort(begin(A), end(A));
    vector&lt;int&gt; cur;
    vector&lt;int&gt; used(A.size());
    int ans = 0;
    dfs(A, cur, used, ans);
    return ans;
  }
private:
  bool squareful(int x, int y) {
    int s = sqrt(x + y);
    return s * s == x + y;
  }
  
  void dfs(const vector&lt;int&gt;&amp; A, vector&lt;int&gt;&amp; cur, vector&lt;int&gt;&amp; used, int&amp; ans) {    
    if (cur.size() == A.size()) {
      ++ans;
      return;
    }
    for (int i = 0; i &lt; A.size(); ++i) {
      if (used[i]) continue;
      // Avoid duplications.
      if (i &gt; 0 &amp;&amp; !used[i - 1] &amp;&amp; A[i] == A[i - 1]) continue; 
      // Prune invalid solutions.
      if (!cur.empty() &amp;&amp; !squareful(cur.back(), A[i])) continue;
      
      cur.push_back(A[i]);
      used[i] = 1;
      dfs(A, cur, used, ans);
      used[i] = 0;
      cur.pop_back();
    }
  }
};</pre>
</div></div>



<h2><strong>Solution 2:&nbsp;DP&nbsp;Hamiltonian&nbsp;Path</strong></h2>



<p>dp[s][i] := # of ways to reach state s (binary mask of nodes visited) that ends with node i</p>



<p>dp[s | (1 &lt;&lt; j)][j] += dp[s][i] if g[i][j]</p>



<p>Time complexity: O(n^2*2^n)<br>Space complexity: O(2^n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, running time: 20 ms, 14.9 MB
class Solution {
public:
  int numSquarefulPerms(vector&lt;int&gt;&amp; A) {
    const int n = A.size();
    // For deduplication.
    std::sort(begin(A), end(A));        
    // g[i][j] == 1 if A[i], A[j] are squareful.
    vector&lt;vector&lt;int&gt;&gt; g(n, vector&lt;int&gt;(n)); 
    // dp[s][i] := number of ways to reach state s and ends with node i.
    vector&lt;vector&lt;int&gt;&gt; dp(1 &lt;&lt; n, vector&lt;int&gt;(n)); 

    for (int i = 0; i &lt; n; ++i) {      
      for (int j = 0; j &lt; n; ++j) {
        if (i == j) continue;
        int r = sqrt(A[i] + A[j]);
        if (r * r == A[i] + A[j])
          g[i][j] = 1;
      }
    }
    
    // For the same numbers, only the first one can be the starting point.
    for (int i = 0; i &lt; n; ++i)
      if (i == 0 || A[i] != A[i - 1])
        dp[(1 &lt;&lt; i)][i] = 1;    
    
    int ans = 0;
    for (int s = 0; s &lt; (1 &lt;&lt; n); ++s)
      for (int i = 0; i &lt; n; ++i) {
        if (!dp[s][i]) continue;
        for (int j = 0; j &lt; n; ++j) {
          if (!g[i][j]) continue;
          if (s &amp; (1 &lt;&lt; j)) continue;
          // Only the first one can be used as the dest.
          if (j &gt; 0 &amp;&amp; !(s &amp; (1 &lt;&lt; (j - 1))) &amp;&amp; A[j - 1] == A[j]) continue;
          dp[s | (1 &lt;&lt; j)][j] += dp[s][i];
        }
      }
    
    for (int i = 0; i &lt; n; ++i)
      ans += dp[(1 &lt;&lt; n) - 1][i];
    return ans;
  }
};</pre>
</div></div>



<h2><strong>Related Problems</strong></h2>



<ul><li><a href="https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/">https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/</a></li><li><a href="https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/">https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/</a></li></ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-996-number-of-squareful-arrays/">花花酱 LeetCode 996. Number of Squareful Arrays</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-996-number-of-squareful-arrays/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 980. Unique Paths III</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 20 Jan 2019 17:21:28 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[Hamiltonian path]]></category>
		<category><![CDATA[hard]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4676</guid>

					<description><![CDATA[<p>On a 2-dimensional&#160;grid, there are 4 types of squares: 1&#160;represents the starting square.&#160; There is exactly one starting square. 2&#160;represents the ending square.&#160; There is&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/">花花酱 LeetCode 980. Unique Paths III</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 980. Unique Paths III - 刷题找工作 EP242" width="500" height="375" src="https://www.youtube.com/embed/dSXtmaGr4Fc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>On a 2-dimensional&nbsp;<code>grid</code>, there are 4 types of squares:</p>



<ul><li><code>1</code>&nbsp;represents the starting square.&nbsp; There is exactly one starting square.</li><li><code>2</code>&nbsp;represents the ending square.&nbsp; There is exactly one ending square.</li><li><code>0</code>&nbsp;represents empty squares we can walk over.</li><li><code>-1</code>&nbsp;represents obstacles that we cannot walk over.</li></ul>



<p>Return the number of 4-directional walks&nbsp;from the starting square to the ending square, that&nbsp;<strong>walk over every non-obstacle square&nbsp;exactly once</strong>.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>[[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
<strong>Output: </strong>2
<strong>Explanation: </strong>We have the following two paths: 
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>[[1,0,0,0],[0,0,0,0],[0,0,0,2]]
<strong>Output: </strong>4
<strong>Explanation: </strong>We have the following four paths: 
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>[[0,1],[2,0]]
<strong>Output: </strong>0
<strong>Explanation: </strong>
There is no path that walks over every empty square exactly once.
Note that the starting and ending square can be anywhere in the grid.
</pre>



<p><strong>Note:</strong></p>



<ol><li><code>1 &lt;= grid.length * grid[0].length &lt;= 20</code></li></ol>



<p>count how many empty blocks there are and try all possible paths to end point and check whether we visited every empty blocks or not.</p>



<h2><strong>Solution:&nbsp;Brute force / DP</strong></h2>



<figure class="wp-block-image"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/01/980-ep242.png" alt="" class="wp-image-4681" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/01/980-ep242.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/01/980-ep242-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/01/980-ep242-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<div class="responsive-tabs">
<h2 class="tabtitle">C++/DFS</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">class Solution {
public:
  int uniquePathsIII(vector&lt;vector&lt;int&gt;&gt;&amp; grid) {    
    int sx = -1;
    int sy = -1;
    int n = 1;
    for (int i = 0; i &lt; grid.size(); ++i)
      for (int j = 0; j &lt; grid[0].size(); ++j)
        if (grid[i][j] == 0) ++n;
        else if (grid[i][j] == 1) { sx = j; sy = i; }    
    return dfs(grid, sx, sy, n);
  }
private:
  int dfs(vector&lt;vector&lt;int&gt;&gt;&amp; grid, int x, int y, int n) {
    if (x &lt; 0 || x == grid[0].size() || 
        y &lt; 0 || y == grid.size() || 
        grid[y][x] == -1) return 0;
    if (grid[y][x] == 2) return n == 0;    
    grid[y][x] = -1;
    int paths = dfs(grid, x + 1, y, n - 1) + 
                dfs(grid, x - 1, y, n - 1) +
                dfs(grid, x, y + 1, n - 1) + 
                dfs(grid, x, y - 1, n - 1);
    grid[y][x] = 0;
    return paths;
  };
};</pre>

</div><h2 class="tabtitle">C++/DP</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">class Solution {
public:
  int uniquePathsIII(vector&lt;vector&lt;int&gt;&gt;&amp; grid) {
    const int n = grid.size();
    const int m = grid[0].size();
    const vector&lt;int&gt; dirs{-1, 0, 1, 0, -1};
    
    vector&lt;vector&lt;vector&lt;short&gt;&gt;&gt; cache(n, vector&lt;vector&lt;short&gt;&gt;(m, vector&lt;short&gt;(1 &lt;&lt; n * m, -1)));
    int sx = -1;
    int sy = -1;
    int state = 0;
    
    auto key = [m](int x, int y) { return 1 &lt;&lt; (y * m + x); };
    
    function&lt;short(int, int, int)&gt; dfs = [&amp;](int x, int y, int state) {    
      if (cache[y][x][state] != -1) return cache[y][x][state];
      if (grid[y][x] == 2) return static_cast&lt;short&gt;(state == 0); 
      int paths = 0;      
      for (int i = 0; i &lt; 4; ++i) {
        const int tx = x + dirs[i];
        const int ty = y + dirs[i + 1];
        if (tx &lt; 0 || tx == m || ty &lt; 0 || ty == n || grid[ty][tx] == -1) continue;
        if (!(state &amp; key(tx, ty))) continue;
        paths += dfs(tx, ty, state ^ key(tx, ty));
      }
      return cache[y][x][state] = paths;
    };
    
    for (int y = 0; y &lt; n; ++y)
      for (int x = 0; x &lt; m; ++x)
        if (grid[y][x] == 0 || grid[y][x] == 2) state |= key(x, y);
        else if (grid[y][x] == 1) { sx = x; sy = y; }
    return dfs(sx, sy, state);
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/">花花酱 LeetCode 980. Unique Paths III</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-980-unique-paths-iii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 943. Find the Shortest Superstring</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 18 Nov 2018 23:10:30 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[Hamiltonian path]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[NPC]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[TSP]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4343</guid>

					<description><![CDATA[<p>Problem Given an array A of strings, find any&#160;smallest string that contains each string in&#160;A&#160;as a&#160;substring. We may assume that no string in&#160;A&#160;is substring of&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/">花花酱 LeetCode 943. Find the Shortest Superstring</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/u_Wc4jwrp3Q?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>Given an array A of strings, find any&nbsp;smallest string that contains each string in&nbsp;<code>A</code>&nbsp;as a&nbsp;substring.</p>
<p>We may assume that no string in&nbsp;<code>A</code>&nbsp;is substring of another string in&nbsp;<code>A</code>.</p>
<div>
<p><strong>Example 1:</strong></p>
<pre class="crayon:false"><strong>Input: </strong><span id="example-input-1-1">["alex","loves","leetcode"]</span>
<strong>Output: </strong><span id="example-output-1">"alexlovesleetcode"</span>
<strong>Explanation: </strong>All permutations of "alex","loves","leetcode" would also be accepted.
</pre>
<div>
<p><strong>Example 2:</strong></p>
<pre class="crayon:false"><strong>Input: </strong><span id="example-input-2-1">["catg","ctaagt","gcta","ttca","atgcatc"]</span>
<strong>Output: </strong><span id="example-output-2">"gctaagttcatgcatc"</span></pre>
</div>
</div>
<p><strong>Note:</strong></p>
<ol>
<li><code>1 &lt;= A.length &lt;= 12</code></li>
<li><code>1 &lt;= A[i].length &lt;= 20</code></li>
</ol>
<p><img class="alignnone size-full wp-image-4352" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/943-ep231.png" alt="" width="960" height="540"></p>
<h1><strong>Solution 1: Search +&nbsp;Pruning</strong></h1>
<p>Try all permutations. Pre-process the cost from word[i] to word[j] and store it in g[i][j].</p>
<p>Time complexity: O(n!)</p>
<p>Space complexity: O(n)</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua, running time: 692 ms
class Solution {
public:
  string shortestSuperstring(vector&lt;string&gt;&amp; A) {    
    const int n = A.size();
    g_ = vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(n));
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; n; ++j) {
        g_[i][j] = A[j].length();
        for (int k = 1; k &lt;= min(A[i].length(), A[j].length()); ++k)
          if (A[i].substr(A[i].size() - k) == A[j].substr(0, k))            
            g_[i][j] = A[j].length() - k;
      }
    vector&lt;int&gt; path(n);
    best_len_ = INT_MAX;
    dfs(A, 0, 0, 0, path);    
    string ans = A[best_path_[0]];
    for (int k = 1; k &lt; best_path_.size(); ++k) {
      int i = best_path_[k - 1];
      int j = best_path_[k];
      ans += A[j].substr(A[j].length() - g_[i][j]);
    }
    return ans;
  }
private:
  vector&lt;vector&lt;int&gt;&gt; g_;
  vector&lt;int&gt; best_path_;
  int best_len_;
  void dfs(const vector&lt;string&gt;&amp; A, int d, int used, int cur_len, vector&lt;int&gt;&amp; path) {
    if (cur_len &gt;= best_len_) return;
    if (d == A.size()) {
      best_len_ = cur_len;
      best_path_ = path;
      return;
    }
    
    for (int i = 0; i &lt; A.size(); ++i) {
      if (used &amp; (1 &lt;&lt; i)) continue;      
      path[d] = i;
      dfs(A,
          d + 1, 
          used | (1 &lt;&lt; i),
          d == 0 ? A[i].length() : cur_len + g_[path[d - 1]][i],
          path);
    }
  }
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua, 439 ms, 35.8MB
class Solution {
  private int n;
  private int[][] g;
  private String[] a;
  private int best_len;
  private int[] path;
  private int[] best_path;
  
  private void dfs(int d, int used, int cur_len) {
    if (cur_len &gt;= best_len) return;
    if (d == n) {
      best_len = cur_len;
      best_path = path.clone();
      return;
    }
    
    for (int i = 0; i &lt; n; ++i) {
      if ((used &amp; (1 &lt;&lt; i)) != 0) continue;
      path[d] = i;
      dfs(d + 1, 
          used | (1 &lt;&lt; i), 
          d == 0 ? a[i].length() : cur_len + g[path[d - 1]][i]);
    }
  }
  
  public String shortestSuperstring(String[] A) {
    n = A.length;
    g = new int[n][n];
    a = A;
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; n; ++j) {
        g[i][j] = A[j].length();
        for (int k = 1; k &lt;= Math.min(A[i].length(), A[j].length()); ++k)
          if (A[i].substring(A[i].length() - k).equals(A[j].substring(0, k)))
            g[i][j] = A[j].length() - k;        
      }
    
    path = new int[n];
    best_len = Integer.MAX_VALUE;
    
    dfs(0, 0, 0);
    
    String ans = A[best_path[0]];
    for (int k = 1; k &lt; n; ++k) {
      int i = best_path[k - 1];
      int j = best_path[k];
      ans += A[j].substring(A[j].length() - g[i][j]);      
    }
    return ans;
  }
}</pre><p></div></div></p>
<h1><strong>Solution 2: DP</strong></h1>
<p>g[i][j] is the cost of appending word[j] after word[i], or weight of edge[i][j].</p>
<p>We would like find the shortest path to visit each node from 0 to n &#8211; 1 once and only once this is called&nbsp;the Travelling sells man&#8217;s problem which is NP-Complete.</p>
<p>We can solve it with DP that uses exponential time.</p>
<p>dp[s][i] := min distance to visit nodes (represented as a binary state s) once and only once and the path ends with node i.</p>
<p>e.g. dp[7][1] is the min distance to visit nodes (0, 1, 2) and ends with node 1, the possible paths could be (0, 2, 1), (2, 0, 1).</p>
<p>Time complexity: O(n^2 * 2^n)</p>
<p>Space complexity: O(n * 2^n)</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua, running time: 20 ms
class Solution {
public:
  string shortestSuperstring(vector&lt;string&gt;&amp; A) {        
    const int n = A.size();
    vector&lt;vector&lt;int&gt;&gt; g(n, vector&lt;int&gt;(n));
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; n; ++j) {
        g[i][j] = A[j].length();
        for (int k = 1; k &lt;= min(A[i].length(), A[j].length()); ++k)
          if (A[i].substr(A[i].size() - k) == A[j].substr(0, k)) 
            g[i][j] = A[j].length() - k;
      }
    
    vector&lt;vector&lt;int&gt;&gt; dp(1 &lt;&lt; n, vector&lt;int&gt;(n, INT_MAX / 2));
    vector&lt;vector&lt;int&gt;&gt; parent(1 &lt;&lt; n, vector&lt;int&gt;(n, -1));
    
    for (int i = 0; i &lt; n; ++i) dp[1 &lt;&lt; i][i] = A[i].length();
    
    for (int s = 1; s &lt; (1 &lt;&lt; n); ++s) {
      for (int j = 0; j &lt; n; ++j) {
        if (!(s &amp; (1 &lt;&lt; j))) continue;
        int ps = s &amp; ~(1 &lt;&lt; j);
        for (int i = 0; i &lt; n; ++i) {
          if (dp[ps][i] + g[i][j] &lt; dp[s][j]) {
            dp[s][j] = dp[ps][i] + g[i][j];
            parent[s][j] = i;
          }
        }
      }
    }
    
    auto it = min_element(begin(dp.back()), end(dp.back()));
    int j = it - begin(dp.back());
    int s = (1 &lt;&lt; n) - 1;
    string ans;
    while (s) {
      int i = parent[s][j];
      if (i &lt; 0) ans = A[j] + ans;
      else ans = A[j].substr(A[j].length() - g[i][j]) + ans;
      s &amp;= ~(1 &lt;&lt; j);
      j = i;
    }
    return ans;
  } 
};</pre><p></div></div></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/">花花酱 LeetCode 943. Find the Shortest Superstring</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-943-find-the-shortest-superstring/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
