Cod sursa(job #1743712)

Utilizator PTAdrian64Pop-Tifrea Adrian PTAdrian64 Data 18 august 2016 16:39:31
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.65 kb
using namespace std;
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define Nmax 18
#define Lmax 30010
#define INF 1000000000
 
int used, best[1 << Nmax][Nmax], pred[1 << Nmax][Nmax];
char words[Nmax][Lmax];
int G[Nmax][Nmax];
 
void make_phi(int[], char[]);
int kmp(char[], char[], int[]);
 
int main()
{
    int i, j, k, n, mask;
    int phi[Lmax], length[Nmax];
    ifstream fin("adn.in");
    ofstream fout("adn.out");
 
    (fin >> n).ignore();
    for (i = 0; i < n; ++i) { fin.getline(words[i] + 1, Lmax); length[i] = strlen(words[i] + 1); }
 
    for (i = 0; i < n; ++i)
    {
        make_phi(phi, words[i]);
 
        for (j = 0; j < n; ++j)
            if (i != j)
            {
                int ret = kmp(words[j], words[i], phi);
 
                if (ret == length[i]) { used |= 1 << i; break; }
                else G[j][i] = length[i] - ret;
            }
    }
 
    for (i = 1; i < (1 << n); ++i) for (j = 0; j < n; ++j) best[i][j] = INF;
    for (i = 0; i < n; ++i) best[1 << i][i] = length[i];
 
    for (i = 1; i < (1 << n); ++i)
        if ((i & used) == 0 && (i & (i - 1)))
        {
            for (j = 0; j < n; ++j)
                if (i & (1 << j))
                {
                    for (k = 0; k < n; ++k)
                        if (j != k && (i & (1 << k)) && best[i][j] > best[i ^ (1 << j)][k] + G[k][j])
                            best[i][j] = best[i ^ (1 << j)][k] + G[k][j],
                            pred[i][j] = k;
                }
        }
 
    mask = ((1 << n) - 1) ^ used;
    for (k = -1, j = 0; j < n; ++j)
    {
        if ((used & (1 << j)) == 0)
            if (k == -1 || best[mask][j] < best[mask][k])
                k = j;
    }
 
    string sol;
    for (i = mask; i; k = j)
    {
        j = pred[i][k];
        i ^= 1 << k;
        if(i) sol.insert(sol.begin(), words[k] + length[k] + 1 - G[j][k], words[k] + length[k] + 1);
        else sol.insert(sol.begin(), words[k] + 1, words[k] + length[k] + 1);
    }
 
    fout << sol << '\n';
 
    fin.close();
    fout.close();
 
    return 0;
}
 
void make_phi(int phi[], char s[])
{
    phi[1] = 0;
    for (int k = 0, i = 2; s[i]; ++i)
    {
        while (k && s[i] != s[k + 1]) k = phi[k];
        if (s[i] == s[k + 1]) ++k;
        phi[i] = k;
    }
}
 
int kmp(char s[], char p[], int phi[])
{
    int i, k;
 
    for (k = 0, i = 1; s[i]; ++i)
    {
        while (k && p[k + 1] != s[i])
            k = phi[k];
        if (p[k + 1] == s[i]) ++k;
 
        if (p[k + 1] == '\0') return k;
    }
 
    return k;
}