Cod sursa(job #2119541)

Utilizator Alex18maiAlex Enache Alex18mai Data 1 februarie 2018 13:41:53
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.03 kb
#include <fstream>
#include <vector>

using namespace std;

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

string s[20];

unsigned long long H[20][30100];
unsigned long long put[30100];

const unsigned long long base = 197;

int lung[20][20];
bool ignore[20];

const int max_mask = 1 << 18;

int dp[max_mask][20];

int n;

void make_H(){

    for (int i=1; i<=n; i++){
        for (int j=1; j<=(int)s[i].size(); j++){
            H[i][j] = H[i][j-1];
            H[i][j] *= base;
            H[i][j] += s[i][j-1];

        }
    }

    put[0] = 1;

    for (int i=1; i<=30000; i++){
        put[i] = put[i-1] * base;
    }

}

void make_lung(){

    for (int i=1; i<=n; i++){
        if (ignore[i]){
            continue;
        }
        for (int j=1; j<=n; j++){
            if (i == j){
                continue;
            }
            if (ignore[j]){
                continue;
            }

            if (s[i].size() <= s[j].size()){
                for (int k=0; k + s[i].size() <= s[j].size(); k++){
                    unsigned long long H1 = H[i][s[i].size()];
                    unsigned long long H2 = H[j][k + s[i].size()] - H[j][k] * put[s[i].size()];

                    if (H1 == H2){
                        ignore[i] = true;
                        break;
                    }
                }
            }

            if (ignore[i]){
                continue;
            }

            int same = 0;

            for (int k = max(0 , (int)s[i].size() - (int)s[j].size()); k < s[i].size(); k++){
                unsigned long long H1 = H[i][s[i].size()] - H[i][k] * put[s[i].size() - k];
                unsigned long long H2 = H[j][s[i].size() - k];

                if (H1 == H2){
                    same = (int)s[i].size() - k;
                    break;
                }
            }

            lung[i][j] = (int)s[j].size() - same;

        }
    }

}

vector <char> ans;

int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin>>n;

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

    make_H();

    make_lung();

    for (int mask = 1; mask < (1 << n); mask++){
        for (int bit = 0; bit < n; bit++){
            dp[mask][bit] = 1e9;
        }
    }

    for (int i=0; i<n; i++){
        if (ignore[i+1]){
            continue;
        }
        dp[(1 << i)][i] = (int)s[i+1].size();
    }

    for (int mask = 0; mask < (1 << n); mask++){
        for (int last = 0; last < n; last++){
            if (ignore[last+1]){
                continue;
            }
            if (!((1 << last) & mask)){
                continue;
            }
            for (int bit = 0; bit < n; bit++){
                if (ignore[bit+1]){
                    continue;
                }
                if ((1 << bit) & mask){
                    continue;
                }
                int now_mask = mask ^ (1 << bit);
                dp[now_mask][bit] = min (dp[now_mask][bit] , dp[mask][last] + lung[last+1][bit+1]);
            }
        }
    }

    int mask_fin = (1 << n) - 1;

    for (int i=0; i<n; i++){
        if (ignore[i+1]){
            mask_fin ^= (1 << i);
        }
    }

    int l = 1e9;
    int last = 0;

    for (int i=0; i<n; i++){
        if (ignore[i+1]){
            continue;
        }
        if (l > dp[mask_fin][i]){
            l = dp[mask_fin][i];
            last = i;
        }
    }

    while (mask_fin){

        mask_fin ^= (1 << last);

        for (int i=0; i<n; i++){
            if ((1 << i) & mask_fin){
                if (dp[mask_fin][i] == l - lung[i+1][last+1]){
                    for (int j = (int)s[last+1].size() - 1; j >= (int)s[last+1].size() - lung[i+1][last+1]; j--){
                        ans.push_back(s[last+1][j]);
                    }
                    l -= lung[i+1][last+1];
                    last = i;
                    break;
                }
            }
        }

    }

    for (int i=(int)s[last+1].size() - 1; i>=0; i--){
        ans.push_back(s[last+1][i]);
    }

    for (int i=(int)ans.size()-1; i>=0; i--){
        cout<<ans[i];
    }

    return 0;
}