Cod sursa(job #1482732)

Utilizator hrazvanHarsan Razvan hrazvan Data 7 septembrie 2015 20:42:22
Problema ADN Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 3 kb
#include <stdio.h>
#define MAXN 18
#define MAXL 30000
#define INF 1000000000
char s[MAXN][MAXL + 2];
int l[MAXN], cost[MAXN][MAXN];
int d[MAXN][(1 << MAXN) - 1];
char ot[MAXL * MAXN + 1];
int dr = 0;
int pi[MAXL];
char bun[MAXN];

inline int max2(int a, int b){
  return a > b ? a : b;
}

inline char inc(int a, int b){
  int k = -1, i;
  for(i = 0; i < l[b]; i++){
    while(k != -1 && s[a][k + 1] != s[b][i])
      k = pi[k];
    if(s[a][k + 1] == s[b][i])
      k++;
    if(k == l[a] - 1)
      return 1;
  }
  return 0;
}

inline void calcpi(int a){
  int k = -1, i;
  pi[0] = -1;
  for(i = 1; i < l[a]; i++){
    while(k != -1 && s[a][i] != s[a][k + 1])
      k = pi[k];
    if(s[a][i] == s[a][k + 1])
      k++;
    pi[i] = k;
  }
}

inline void copy(int a, int b){
  int i;
  for(i = 0; i < l[b]; i++)
    s[a][i] = s[b][i];
  l[a] = l[b];
}

inline void verif(int *n){
  int i, j;
  for(i = 0; i < *n; i++)
    bun[i] = 1;
  for(i = 0; i < *n; i++){
    if(bun[i]){
      calcpi(i);
      for(j = 0; j < *n; j++){
        if(i != j && bun[j] && l[i] <= l[j]){
          if(inc(i, j))
            bun[i] = 0;
        }
      }
    }
  }
  j = 0;
  for(i = 0; i < *n; i++){
    if(bun[i]){
      copy(j, i);
      j++;
    }
  }
  *n = j;
}

inline void calccost(int n){
  int i, j, k, t;
  for(i = 0; i < n; i++){
    calcpi(i);
    for(j = 0; j < n; j++){
      if(i != j){
        k = -1;
        for(t = 0; t < l[j]; t++){
          while(k != -1 && s[i][k + 1] != s[j][t])
            k = pi[k];
          if(s[i][k + 1] == s[j][t])
            k++;
        }
        cost[i][j] = k + 1;
      }
    }
  }
}

int solve(int bin, int x, int n){
  int i;
  if(d[x][bin] == -INF)
    for(i = 0; i < n; i++)
      if(bin & (1 << i))
        d[x][bin] = max2(d[x][bin], solve(bin - (1 << i), i, n) + cost[x][i]);
  return d[x][bin];
}

void recon(int bin, int x, int n){
  int i, j;
  if(bin == 0){
    for(i = 0; i < l[x]; i++){
      ot[dr] = s[x][i];
      dr++;
    }
  }
  else{
    for(i = 0; i < n; i++){
      if((bin & (1 << i)) && d[x][bin] == d[i][bin - (1 << i)] + cost[x][i]){
        recon(bin - (1 << i), i, n);
        for(j = cost[x][i]; j < l[x]; j++){
          ot[dr] = s[x][j];
          dr++;
        }
        i = n;
      }
    }
  }
}

int main(){
  FILE *in = fopen("adn.in", "r");
  int n, i;
  fscanf(in, "%d ", &n);
  for(i = 0; i < n; i++){
    fgets(s[i], MAXL + 2, in);
    l[i] = 0;
    while(s[i][l[i]] != '\n')
      l[i]++;
  }
  fclose(in);
  verif(&n);
  calccost(n);
  int rez = -INF, p = -1, x, j;
  for(i = 0; i < n; i++)
    for(j = 0; j < (1 << n); j++)
      d[i][j] = -INF;
  for(j = 0; j < n; j++)
    d[j][0] = 0;
  for(i = 0; i < n; i++){
    x = solve((1 << n) - 1 - (1 << i), i, n);
    if(x > rez){
      rez = x;
      p = i;
    }
  }
  recon((1 << n) - 1 - (1 << p), p, n);
  FILE *out = fopen("adn.out", "w");
  fputs(ot, out);
  fclose(out);
  return 0;
}