Cod sursa(job #2165273)

Utilizator cella.florescuCella Florescu cella.florescu Data 13 martie 2018 11:41:02
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.93 kb
#include <fstream>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 18;
const int MAXL = 3e4;
const int INF = 0x3f3f3f3f;

string w[MAXN], v[MAXN];
int in[MAXN][MAXN], cost[MAXN][MAXN], dp[MAXN][1 << MAXN], pi[2 * MAXL + 3], prv[MAXN][1 << MAXN];

int contains(string& big, string& small) {
  if (big.size() == small.size() && big == small)
    return 1;
  if (big.size() < small.size())
    return 0;
  int k = 0;
  memset(pi, 0, sizeof pi);
  for (int i = 2; i <= (int) small.size(); ++i) {
    for (k = k; k > 0 && small[i - 1] != small[k]; k = pi[k]) {}
    pi[i] = (k += (small[i - 1] == small[k]));
  }
  k = 0;
  for (int i = 1; i <= (int) big.size(); ++i) {
    for (k = k; k > 0 && small[k] != big[i - 1]; k = pi[k]) {}
    if ((k += small[k] == big[i - 1]) == (int) small.size())
      return 1;
  }
  return 0;
}

inline int to_add(string& a, string& b) {
  string s = b + '$' + a;
  memset(pi, 0, sizeof pi);
  int k = 0;
  for (int i = 2; i <= (int) s.size(); ++i) {
    for (k = k; k > 0 && s[i - 1] != s[k]; k = pi[k]) {}
    pi[i] = (k += (s[i - 1] == s[k]));
  }
  return (int) b.size() - pi[s.size()];
}

int main()
{
    int n, m = 0;
    ifstream fin("adn.in");
    fin >> n;
    for (int i = 0; i < n; ++i)
      fin >> w[i];
    fin.close();
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j)
        in[i][j] = contains(w[j], w[i]);
    for (int i = 0; i < n; ++i) {
      int ok = 1;
      for (int j = 0; j < n; ++j)
        if ((in[i][j] == 0 || in[i][j] && in[j][i] && i <= j) == 0)
          ok = 0;
      if (ok)
        v[m++] = w[i];
    }
    memset(dp, INF, sizeof dp);
    memset(prv, -1, sizeof prv);
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < m; ++j)
        cost[i][j] = to_add(v[i], v[j]);
      dp[i][1 << i] = (int) v[i].size();
      prv[i][1 << i] = i;
    }
    for (int conf = 3; conf < (1 << m); ++conf)
      if (conf & (conf - 1))
        for (int lst = 0; lst < m; ++lst)
          if (conf & (1 << lst))
            for (int p = 0; p < m; ++p)
              if ((p ^ lst) && (conf & (1 << p)) && dp[p][conf ^ (1 << lst)] + cost[p][lst] < dp[lst][conf]) {
                dp[lst][conf] = dp[p][conf ^ (1 << lst)] + cost[p][lst];
                prv[lst][conf] = p;
              }
    int ind = 0, cnf = (1 << m) - 1;
    for (int i = 1; i < m; ++i)
      if (dp[i][cnf] < dp[ind][cnf])
        ind = i;
    vector <int> sol;
    while (prv[ind][cnf] != -1) {
      sol.push_back(ind);
      int aux = prv[ind][cnf];
      cnf ^= (1 << ind);
      ind = aux;
    }
    reverse(sol.begin(), sol.end());
    ofstream fout("adn.out");
    fout << v[sol[0]];
    for (int i = 1; i < m; ++i)
      for (int j = (int) v[sol[i]].size() - cost[sol[i - 1]][sol[i]]; j < (int) v[sol[i]].size(); ++j)
        fout << v[sol[i]][j];
    fout.close();
    return 0;
}