Cod sursa(job #2927454)

Utilizator Alex_tz307Lorintz Alexandru Alex_tz307 Data 20 octombrie 2022 16:50:50
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.37 kb
#include <bits/stdc++.h>

using namespace std;

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

const int kN = 18;
int wt[kN][kN];
pair<int, int> dp[kN][1 << kN];

void maxSelf(int &x, int y) {
  if (x < y) {
    x = y;
  }
}

vector<int> preffixFunction(const string &s) {
  int n = s.size() - 1;
  vector<int> pi(n + 1);
  for (int i = 2, q = 0; i <= n; ++i) {
    while (q && s[q + 1] != s[i]) {
      q = pi[q];
    }
    if (s[q + 1] == s[i]) {
      q += 1;
    }
    pi[i] = q;
  }
  return pi;
}

bool check(const string &s, const string &t) {
  vector<int> pi = preffixFunction('#' + s + '#' + t);
  if (*max_element(pi.begin(), pi.end()) == (int)s.size()) {
    return true;
  }
  return false;
}

int findSuffix(const string &s, const string &t) {
  return preffixFunction('#' + s + '#' + t).back();
}

int main() {
  int n;
  fin >> n;
  vector<string> s(n);
  for (auto &it : s) {
    fin >> it;
  }
  vector<string> newS;
  for (int i = 0; i < n; ++i) {
    bool flag = true;
    for (int j = 0; j < n; ++j) {
      if (i != j && check(s[i], s[j])) {
        flag = false;
        break;
      }
    }
    if (flag) {
      newS.emplace_back(s[i]);
    }
  }
  s = newS;
  n = s.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i != j) {
        wt[i][j] = findSuffix(s[j], s[i]);
      }
    }
  }
  for (int mask = 3; mask < (1 << n); ++mask) {
    if (__builtin_popcount(mask) > 1) {
      for (int start = 0; (1 << start) <= mask; ++start) {
        if (mask & (1 << start)) {
          int newMask = mask ^ (1 << start);
          for (int nxt = 0; (1 << nxt) <= newMask; ++nxt) {
            if (newMask & (1 << nxt)) {
              dp[start][mask] = max(dp[start][mask], {dp[nxt][newMask].first + wt[start][nxt], nxt});
            }
          }
        }
      }
    }
  }
  int best = 0, curr = 0, mask = (1 << n) - 1;
  for (int i = 0; i < n; ++i) {
    if (best < dp[i][mask].first) {
      best = dp[i][mask].first;
      curr = i;
    }
  }
  int pref = 0;
  string sol = "";
  while (mask) {
    for (int i = pref; i < (int)s[curr].size(); ++i) {
      sol += s[curr][i];
    }
    int nxt = dp[curr][mask].second;
    mask ^= 1 << curr;
    pref = wt[curr][nxt];
    curr = nxt;
  }
  fout << sol << '\n';
  fin.close();
  fout.close();
  return 0;
}