Cod sursa(job #865694)

Utilizator ELHoriaHoria Cretescu ELHoria Data 26 ianuarie 2013 20:51:59
Problema ADN Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.42 kb
#include <fstream>
#include <vector>
#include <string>
#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];
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) {
	if(pos == -1) {
		if(isSet(state,who[state][v])) {
			buildSolution(state ^ (1<<v),who[state][v],s[who[state][v]].size() - P[who[state][v]][v] - 1);
		}
	} else {
		buildSolution(state,v,pos - 1);
		cout<<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);
}

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