สมมติว่าเรามีอาร์เรย์ A ของสตริง เราต้องหาสตริงที่เล็กที่สุดที่มีแต่ละสตริงใน A เป็นสตริงย่อย นอกจากนี้เรายังสามารถสรุปได้ว่าไม่มีสตริงใดใน A เป็นสตริงย่อยของสตริงอื่นใน A.
ดังนั้น หากอินพุตเป็น ["dbsh","dsbbhs","hdsb","ssdb","bshdbsd"] เอาต์พุตจะเป็น "hdsbbhssdbshdbsd"
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
กำหนดฟังก์ชัน calc() ซึ่งจะใช้เวลา a, b,
-
สำหรับการเริ่มต้น i :=0, เมื่อ i
-
หากสตริงย่อยของ a จากดัชนี i ถึงจุดสิ้นสุดอยู่ที่จุดเริ่มต้นของ b แล้ว −
-
ขนาดส่งคืนของ b - ขนาดของ a + i
-
-
-
ขนาดส่งคืนของ b
-
จากวิธีหลัก ทำตามขั้นตอนเหล่านี้
-
ret :=สตริงว่าง
-
n :=ขนาดของ A
-
กำหนดกราฟอาร์เรย์ 2 มิติขนาด n x n -
-
สำหรับการเริ่มต้น j :=0 เมื่อ j
-
กราฟ[i, j] :=calc(A[i], A[j])
-
กราฟ[j, i] :=calc(A[j], A[i])
-
-
-
กำหนดขนาดอาร์เรย์ dp:2^n x n.
-
กำหนดเส้นทางอาร์เรย์ขนาด:2^n x n.
-
minVal :=inf
-
สุดท้าย :=-1
-
สำหรับการเริ่มต้น i :=0 เมื่อ i <2^n อัปเดต (เพิ่ม i ขึ้น 1) ทำ −
-
สำหรับการเริ่มต้น j :=0 เมื่อ j
-
dp[i, j] :=inf
-
-
-
สำหรับการเริ่มต้น i :=0 เมื่อ i <2^n อัปเดต (เพิ่ม i ขึ้น 1) ทำ −
-
สำหรับการเริ่มต้น j :=0 เมื่อ j
-
ถ้า i AND 2^j ไม่ใช่ศูนย์ ดังนั้น
-
ก่อนหน้า :=i ^ (2^j)
-
-
ถ้าก่อนหน้าเท่ากับ 0 ดังนั้น −
-
dp[i, j] :=ขนาดของ A[j]
-
-
มิฉะนั้น
-
สำหรับการเริ่มต้น k :=0 เมื่อ k
-
ถ้าก่อนหน้า AND 2^k และ df[prev,k] ไม่ใช่ inf และ df[prev,k] +graph[k,j]
-
dp[i, j] :=dp[ก่อนหน้า, k] + กราฟ[k, j]
-
เส้นทาง[i, j] :=k
-
-
-
-
-
ถ้าฉันเหมือนกับ 2^n - 1 และ dp[i, j]
-
minVal :=dp[i, j]
-
สุดท้าย :=j
-
-
-
สกุลเงิน :=2^n - 1
-
กำหนดหนึ่งสแต็ก st
-
ในขณะที่ curr> 0, ทำ -
-
ใส่สุดท้ายลงใน st
-
temp :=curr
-
curr :=curr - (2^สุดท้าย)
-
สุดท้าย :=เส้นทาง[ชั่วคราว สุดท้าย]
-
-
ผม :=องค์ประกอบด้านบนของ st
-
ลบองค์ประกอบออกจาก st
-
ret :=ret + A[i]
-
ในขณะที่ (ไม่ใช่ st ว่างเปล่า) ทำ -
-
j :=องค์ประกอบด้านบนของ st
-
ลบองค์ประกอบออกจาก st
-
ret :=ret เชื่อมสตริงย่อยของ A[j] จาก (ขนาดของ A[j] - กราฟ[i,j] ถึงสิ้นสุด)
-
ผม :=เจ
-
-
รีเทิร์น
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include <bits/stdc++.h> using namespace std; class Solution { public: int calc(string& a, string& b){ for (int i = 0; i < a.size(); i++) { if (b.find(a.substr(i)) == 0) { return b.size() - a.size() + i; } } return (int)b.size(); } string shortestSuperstring(vector<string>& A){ string ret = ""; int n = A.size(); vector<vector<int> > graph(n, vector<int>(n)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { graph[i][j] = calc(A[i], A[j]); graph[j][i] = calc(A[j], A[i]); } } int dp[1 << n][n]; int path[1 << n][n]; int minVal = INT_MAX; int last = -1; for (int i = 0; i < (1 << n); i++) for (int j = 0; j < n; j++) dp[i][j] = INT_MAX; for (int i = 1; i < (1 << n); i++) { for (int j = 0; j < n; j++) { if ((i & (1 << j))) { int prev = i ^ (1 << j); if (prev == 0) { dp[i][j] = A[j].size(); } else { for (int k = 0; k < n; k++) { if ((prev & (1 << k)) && dp[prev][k] != INT_MAX && dp[prev][k] + graph[k][j] < dp[i][j]) { dp[i][j] = dp[prev][k] + graph[k][j]; path[i][j] = k; } } } } if (i == (1 << n) - 1 && dp[i][j] < minVal) { minVal = dp[i][j]; last = j; } } } int curr = (1 << n) - 1; stack<int> st; while (curr > 0) { st.push(last); int temp = curr; curr -= (1 << last); last = path[temp][last]; } int i = st.top(); st.pop(); ret += A[i]; while (!st.empty()) { int j = st.top(); st.pop(); ret += (A[j].substr(A[j].size() - graph[i][j])); i = j; } return ret; } }; main(){ Solution ob; vector<string> v = {"dbsh","dsbbhs","hdsb","ssdb","bshdbsd"}; cout << (ob.shortestSuperstring(v)); }
อินพุต
{"dbsh","dsbbhs","hdsb","ssdb","bshdbsd"}
ผลลัพธ์
hdsbbhssdbshdbsd