Cod sursa(job #865699)

Utilizator ELHoriaHoria Cretescu ELHoria Data 26 ianuarie 2013 20:56:31
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.55 kb
#include <fstream>
#include <vector>
#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;
vector<int> G[NMAX];
int P[NMAX][NMAX];
int dp[1<<NMAX][NMAX];
int 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];
		}
	}
	G[pattern].push_back(text);
	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(vector<int>::const_iterator w = G[v].begin();w != G[v].end();++w) {
		if(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;
}