Computer >> 컴퓨터 >  >> 프로그램 작성 >> C++

C++에서 가장 짧은 슈퍼스트링 찾기

<시간/>

문자열 배열 A가 있다고 가정하고 A의 각 문자열을 부분 문자열로 포함하는 가장 작은 문자열을 찾아야 합니다. 또한 A에 있는 어떤 문자열도 A에 있는 다른 문자열의 부분 문자열이 아니라고 가정할 수 있습니다.

따라서 입력이 ["dbsh","dsbbhs","hdsb","ssdb","bshdbsd"]와 같으면 출력은 "hdsbbhssdbshdbsd"

가 됩니다.

이 문제를 해결하기 위해 다음 단계를 따릅니다. −

  • calc() 함수를 정의하면, b,

  • initialize i :=0의 경우, i

    • 인덱스 i에서 끝까지의 부분 문자열이 b의 시작에 있으면 -

      • b의 크기 반환 - + i의 크기

  • b

    의 크기를 반환
  • 기본 방법에서 다음 단계를 수행하십시오.

  • ret :=빈 문자열

  • n :=A의 크기

  • 크기가 n x n −

    인 하나의 2D 배열 그래프를 정의합니다.
    • j 초기화의 경우:=0, j

      • 그래프[i, j] :=calc(A[i], A[j])

      • 그래프[j, i] :=calc(A[j], A[i])

  • 2^n x n 크기의 배열 dp를 정의합니다.

  • 2^n x n 크기의 배열 경로를 정의합니다.

  • minVal :=inf

  • 마지막 :=-1

  • initialize i :=0의 경우, i <2^n일 때 업데이트(i를 1만큼 증가), 수행 -

    • j 초기화의 경우:=0, j

      • dp[i, j] :=정보

  • initialize i :=0의 경우, i <2^n일 때 업데이트(i를 1만큼 증가), 수행 -

    • j 초기화의 경우:=0, j

      • i AND 2^j가 0이 아니면

        • 이전 :=나는 ^ (2^j)

      • prev가 0과 같으면 -

        • dp[i, j] :=A[j]의 크기

      • 그렇지 않으면

        • 초기화 k :=0의 경우 k

          • prev AND 2^k 및 df[prev,k]가 inf가 아니고 df[prev,k] +graph[k,j]

            • dp[i, j] :=dp[이전, k] + 그래프[k, j]

            • 경로[i, j] :=k

    • i가 2^n - 1이고 dp[i, j]

      • minVal :=dp[i,j]

      • 마지막 :=j

  • 커 :=2^n - 1

  • 하나의 스택 정의

  • curr> 0일 때 −

    • st에 마지막 삽입

    • 임시 :=현재

    • curr :=curr - (2^마지막)

    • 마지막 :=경로[임시, 마지막]

  • i :=st의 최상위 요소

  • st

    에서 요소 삭제
  • 렛 :=렛 + A[i]

  • 동안(st가 비어 있지 않음) -

    • j :=st의 최상위 요소

    • st

      에서 요소 삭제
    • ret :=ret A[j]의 부분 문자열을 (A[j]의 크기 - 그래프[i,j]에서 끝까지 연결)

    • 나는 :=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