Cod sursa(job #2452335)

Utilizator gavra_bogdanBogdan Gavra gavra_bogdan Data 30 august 2019 15:03:22
Problema ADN Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.6 kb
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;

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

int const nmax = 18;
int const lmax = 30001;

int const inf = 1000000000;

string v[5 + nmax];
int cost[5 + nmax][5 + nmax];

int pre[5 + 2 * lmax];

#define MAX(a , b) ((a < b) ? b : a)

int getcost(string a , string b){
  int n = b.size();
  a = b + "*" + a;

  int i = 0 , j = 1;
  while(j < a.size()) {
    if(a[i] == a[j]) {
      pre[j] = i + 1;
      i++;
      j++;
    } else {
      if(i == 0){
        pre[j] = 0;
        j++;
      } else  {
        i = pre[i - 1];
      }
    }
  }

  for(int i = b.size() ; i < a.size() ;i++){
    if(pre[i] == b.size()){
      return -1;
    }
  }
  return b.size() - pre[a.size() - 1];
}
int dp[5 + (1 << nmax)][5 + nmax];
int last[5 + (1 << nmax)][5 + nmax];

void printsol(int pos ,int mask){
  int pos2 = last[mask][pos];
  if(-1 < pos2){
    printsol(pos2 , mask ^ (1 << pos));
    for(int i = v[pos].size() - cost[pos2][pos] ; i < v[pos].size() ;i++)
      out << v[pos][i];
  } else
    for(int i = 0 ; i < v[pos].size() ;i++)
      out << v[pos][i];
}

string v2[5 + nmax];
bool sadd[5 + nmax];

bool compare(string a , string b){
  return a.size() < b.size();
}

int main()
{
  int n;
  in >> n;
  for(int i = 0 ; i < n ;i++)
    in >> v2[i];
  sort(v2 , v2 + n , compare);
  int n2 = 0;
  for(int i = n - 1 ; 0 <= i ;i--){
    if(sadd[i] == 0)
      v[n2++] = v2[i];
    for(int j = 0 ; j < i ;j++)
      if(getcost(v2[i] ,v2[j] ) == -1)
        sadd[j] = 1;
  }
  n = n2;

  for(int i = 0 ; i < n ;i++){
    for(int j = 0 ; j < n ;j++){

      if(i != j){
        cost[i][j] = getcost(v[i] , v[j]);
      }
    }
  }
  for(int i = 0 ; i < n ;i++){
    dp[(1 << i)][i] = v[i].size();
    last[(1 << i)][i] = -1;
  }
  for(int mask = 0 ; mask < (1 << n) ;mask++){
    for(int j = 0 ; j < n ;j++){
      if(0 < dp[mask][j] && 0 < (mask & (1 << j))){
        for(int h = 0 ; h < n ;h++){
          if(0 == (mask & (1 << h))){

            int newmask = (mask | (1 << h));
            if(dp[newmask][h] == 0 || dp[mask][j] + cost[j][h] < dp[newmask][h] ){
              dp[newmask][h] = dp[mask][j] + cost[j][h];
              last[newmask][h] = j;
            }
          }
        }
      }
    }
  }
  int smin = inf , sol = 0;
  for(int i = 0 ; i < n ;i++)
    if(0 < dp[(1 << n) - 1][i] ){
      if(dp[(1 << n) - 1][i] < smin){
        smin = dp[(1 << n) - 1][i];
        sol = i;
      }
    }
  printsol(sol , (1 << n) - 1);
  return 0;
}