Cod sursa(job #895989)

Utilizator otto1Palaga Vicentiu-Octavian otto1 Data 27 februarie 2013 13:22:23
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.86 kb
#include <fstream>
#include <string>
#include <algorithm>
#define isSet(a,b) ((a>>b) & 1)

using namespace std;

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

const int inf = int(1e9);
const int LMAX = 30005, NMAX = 18;
int a[NMAX][LMAX];
int disabled;
int N;
string s[NMAX], sol;
int P[NMAX][NMAX];
int dp[1<<NMAX][NMAX];
char who[1<<NMAX][NMAX];

void readData() {
    cin>>N;
    cin.get();
    for(int i = 0;i < N;i++) {
        getline(cin,s[i]);
    }
}

void prefix(const string &str,int pat[LMAX]) {
    int k = 0;
    pat[0] = 0;
    for(int i = 1;i < (int)str.size();i++) {
        while(k > 0 && str[i] != str[k]) k = pat[k - 1];
        if(str[i] == str[k]) k++;
        pat[i] = k;
    }
}

void match(const int &text,const int &pattern) {
    int k = 0;
    for(int i = 0;i < (int)s[text].size();i++) {
        while(k > 0 && s[text][i] != s[pattern][k]) k = a[pattern][k - 1];
        if(s[text][i] == s[pattern][k]) k++;
        if(k == (int)s[pattern].size()) {
            disabled |= (1<<pattern);
            k = a[pattern][k - 1];
        }
    }
    P[text][pattern] = k;
}

int memo(const int &state,const int &v) {
    int &ret = dp[state][v];
    if(ret != inf) return ret;
    ret = ret - 1;
    if((state & (state - 1)) == 0) {
        return ret = (int)s[v].size();
    }
    for(int w = 0;w < N;w++) {
        if(v == w || isSet(disabled,w) || isSet(state,w) == false) continue;
        int cost = s[v].size() + memo(state ^ (1<<v),w) - P[w][v];
        if(cost < ret) {
            ret = cost;
            who[state][v] = w;
        }
    }
    return ret;
}

void buildSolution(int state,int v,int pos) {
    while(state > 0) {
        if(pos == -1) {
            if((state & (state - 1)) == 0) {
                state = 0;
            } else {
                int w = who[state][v];
                pos = s[who[state][v]].size() - P[who[state][v]][v] - 1;
                state ^= (1<<v);
                v = w;
            }

        } else {
            sol += s[v][pos--];
        }
    }
}

void solve() {
    for(int i = 0;i < N;i++) {
        prefix(s[i],a[i]);
    }
    for(int i = 0;i < N;i++) {
        for(int j = 0;j < N;j++) {
            if(i != j) {
                match(i,j);
            }
        }
    }
    for(int i = 0;i < (1<<N);i++) {
        for(int k = 0;k < N;k++) {
            dp[i][k] = inf;
        }
    }

    int notDisabled = ((1<<N) - 1) ^ disabled;
    int ans = inf, bestNode = -1;
    for(int i = 0;i < N;i++) {
        if(isSet(notDisabled,i) && memo(notDisabled,i) < ans) {
            ans = memo(notDisabled,i);
            bestNode = i;
        }
    }
    buildSolution(notDisabled,bestNode,s[bestNode].size() - 1);
    reverse(sol.begin(),sol.end());
    cout<<sol;
}

int main()
{
    readData();
    solve();
    return 0;
}