Cod sursa(job #2240958)

Utilizator lil_blocAnonymous Anonymous lil_bloc Data 14 septembrie 2018 15:47:56
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.73 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <bitset>
#include <vector>

using namespace std;

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

const int NMAX = 3 * 1e4;
const int VMAX = 20;
const int SMAX = (1 << 18) + 20;

int n;
int sum, root;
int d[1 + NMAX];
int p[VMAX][SMAX];
int dp[VMAX][SMAX];
int cost[VMAX][VMAX];

string s[VMAX];
vector < int > sol;
bitset < VMAX > del;

int kmp(string &a, string &b) {
  int k = 0;
  for(int i = 1; i < a.size(); i++) {
    while(k != 0 && a[i] != a[k])
      k = d[k - 1];
    if(a[i] == a[k])
      k++;
    d[i] = k;
  }

  k = 0;
  for(int i = 0; i < b.size(); i++) {
    while (k != 0 && b[i] != a[k])
      k = d[k - 1];
    if(b[i] == a[k])
      k++;
  }

  return k;
}

bool check(string &a, string &b) {
  int k = 0;
  for(int i = 1; i < a.size(); i++) {
    while(k != 0 && a[i] != a[k])
      k = d[k - 1];
    if(a[i] == a[k])
      k++;
    d[i] = k;
  }

  k = 0;
  for(int i = 0; i < b.size(); i++) {
    while(k != 0 && b[i] != a[k])
      k = d[k - 1];
    if(b[i] == a[k])
      k++;
    if(k == a.size())
      return true;
  }

  return false;
}

int main()
{
  in >> n;
  for(int i = 1; i <= n; i++) {
    in >> s[i];
  }

  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= n; j++) {
      if(i != j && del[i] == 0 && del[j] == 0 && s[i].size() <= s[j].size())
        if(check(s[i], s[j]))
          del[i] = 1;
    }
  }

  for(int i = 1; i <= n; i++) {
    while(del[i] && i <= n) {
      swap(s[i], s[n]);
      if(del[n] == 0)
        del[i] = 0;
      else
        del[i] = 1;
      n--;
    }
  }

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

  for(int i = 0; i < (1 << n); i++) {
    for(int j = 0; j < n; j++) {
      p[j][i] = -1;
      if(i & (1 << j)) {
        for(int k = 0; k < n; k++) {
          if(i & (1 << k)) {
            if(dp[k][i ^ (1 << j)] + cost[j][k] > dp[j][i]) {
              p[j][i] = k;
              dp[j][i] = dp[k][i ^ (1 << j)] + cost[j][k];
            }
          }
        }
      }
    }
  }

  for(int i = 0; i < n; i++) {
    if(sum < dp[i][(1 << n) - 1]) {
      sum = dp[i][(1 << n) - 1];
      root = i;
    }
  }

  int i = (1 << n) - 1;
  while(root != -1) {
    sol.push_back(root + 1);
    int aux = p[root][i];
    i -= (1 << root);
    root = aux;
  }

  root = sol.front();
  out << s[root];
  for(int i = 1; i < sol.size(); i++) {
    int from = cost[root - 1][sol[i] - 1];
    out << s[sol[i]].substr(from);
    root = sol[i];
  }

  out << '\n';

  in.close();
  out.close();

  return 0;
}