Cod sursa(job #2177378)

Utilizator Al3ks1002Alex Cociorva Al3ks1002 Data 18 martie 2018 15:09:23
Problema ADN Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.35 kb
#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pdd pair<ld, ld>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second

ifstream fin("adn.in");
ofstream fout("adn.out");

const int kInf = 1LL << 29;

int n;
vector<string> s;
vector<bool> ignored;
vector<vector<int>> cost;
vector<vector<int>> dp;
vector<vector<pii>> where;

class KMP {
 public:
  explicit KMP(const string& text) : text_(text) {}

  pair<int, int> GetMatchingIndexes(const string& pattern) {
    int count = 0;

    vector<int> prefix(pattern.size(), 0);
    BuildPi(pattern, prefix);

    int q = 0;
    for (int i = 0; i < (int)text_.size(); i++) {
      while (q && pattern[q] != text_[i]) {
        q = prefix[q - 1];
      }

      if (pattern[q] == text_[i]) {
        q++;
      }

      if (q == (int)pattern.size()) {
        count++;
      }
    }

    return {count, q};
  }

 private:
  void BuildPi(const string& pattern, vector<int>& prefix) {
    int q = 0;
    for (int i = 1; i < (int)pattern.size(); i++) {
      while (q && pattern[q] != pattern[i]) {
        q = prefix[q - 1];
      }

      if (pattern[q] == pattern[i]) {
        q++;
      }

      prefix[i] = q;
    }
  }

  const string text_;
};

void Read() {
  fin >> n;
  s.resize(n);
  for (int i = 0; i < n; i++) {
    fin >> s[i];
  }
}

void BuildGraph() {
  ignored.resize(n);
  cost.resize(n, vector<int>(n, kInf));
  for (int i = 0; i < n; i++) {
    if (!ignored[i]) {
      KMP kmp(s[i]);
      for (int j = 0; j < n; j++) {
        if (j != i && !ignored[j]) {
          pii match = kmp.GetMatchingIndexes(s[j]);
          if (match.fi) {
            ignored[j] = 1;
          } else {
            cost[i][j] = s[j].size() - match.se;
          }
        }
      }
    }
  }

  for (int i = 0; i < n; i++) {
    if (ignored[i]) {
      swap(s[i], s[n - 1]);
      for (int j = 0; j < n; j++) {
        swap(cost[i][j], cost[n - 1][j]);
        swap(cost[j][i], cost[j][n - 1]);
      }
      n--;
    }
  }
}

void BuildDp() {
  dp.resize(1 << n, vector<int>(n, kInf));
  where.resize(1 << n, vector<pii>(n));

  for (int i = 0; i < n; i++) {
    dp[1 << i][i] = s[i].size();
    where[1 << i][i] = {0, -1};
  }

  for (int i = 1; i < (1 << n); i++) {
    for (int j = 0; j < n; j++) {
      if (dp[i][j] != kInf) {
        if ((1 << j) & i) {
          for (int k = 0; k < n; k++) {
            if (((1 << k) & i) == 0) {
              if (dp[i][j] + cost[j][k] < dp[i + (1 << k)][k]) {
                dp[i + (1 << k)][k] = dp[i][j] + cost[j][k];
                where[i + (1 << k)][k] = {i, j};
              }
            }
          }
        }
      }
    }
  }
}

void Print(int i, int j) {
  if (i == 0) {
    return;
  }

  Print(where[i][j].fi, where[i][j].se);

  int last = where[i][j].se;
  int curr = j;

  if (last == -1) {
    fout << s[curr];
  } else {
    for (int k = s[curr].size() - cost[last][curr]; k < s[curr].size(); k++) {
      fout << s[curr][k];
    }
  }
}

void PrintAnswer() {
  int ans = kInf;
  int x, y;
  for (int i = 0; i < n; i++) {
    if (dp[(1 << n) - 1][i] < ans) {
      ans = dp[(1 << n) - 1][i];
      x = (1 << n) - 1;
      y = i;
    }
  }

  Print(x, y);
}

int main() {
  Read();
  BuildGraph();
  BuildDp();
  PrintAnswer();

  return 0;
}