Pagini recente » Cod sursa (job #1130117) | Cod sursa (job #833066) | Cod sursa (job #1574587) | Cod sursa (job #105627) | Cod sursa (job #2986650)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
const int INF = 0x3f3f3f3f;
struct Edge {
int destination;
int cost;
};
int n;
string str[20];
int lps[60005];
vector <Edge> graph[20];
string a, s;
int costs[20][20];
bool absorbed[20];
int nodesNewToInit[20];
int nodesInitToNew[20];
int dp[1 << 18][20];
int bkt[1 << 18][20];
vector <int> answerIndices;
int LPS(int aIdx, int bIdx) {
s = '$' + str[aIdx] + '$' + str[bIdx];
a = str[aIdx];
int lenS = s.length();
for (int i = 2; i < lenS; i++) {
int currLetter = s[i];
int currIdx = lps[i - 1];
while (currIdx && currLetter != s[currIdx + 1]) {
currIdx = lps[currIdx];
}
if (currLetter == s[currIdx + 1]) {
currIdx++;
}
lps[i] = currIdx;
}
return lenS;
}
void BuildCostsMatrix() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j) {
continue;
}
/*
GGATATAAAAAC = i
TGGGGATATAAAA = j
*/
int lpsSize = LPS(i, j);
int lenA = str[i].length();
int startIdx = lenA + 2;
int currLpsValue = -1;
for (int k = startIdx; k < lpsSize; k++) {
currLpsValue = lps[k];
// Check if it is included
if (lps[k] == lenA) {
absorbed[i] = true;
break;
}
}
costs[j][i] = currLpsValue;
}
}
}
int BuildGraph() {
memset(nodesInitToNew, INF, sizeof(nodesInitToNew));
memset(nodesNewToInit, INF, sizeof(nodesNewToInit));
int nodesCount = 0;
for (int i = 1; i <= n; i++) {
if (absorbed[i]) {
continue;
}
nodesNewToInit[nodesCount] = i;
nodesInitToNew[i] = nodesCount;
nodesCount++;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j) {
continue;
}
if (absorbed[i] || absorbed[j]) {
continue;
}
if (costs[i][j]) {
graph[nodesInitToNew[i]].push_back({nodesInitToNew[j], costs[i][j]});
}
}
}
return nodesCount;
}
void BuildDynamicConfiguration(int nodesCount) {
memset(bkt, INF, sizeof(bkt));
memset(dp, -1, sizeof(dp));
dp[0][0] = 1;
for (int conf = 0; conf < (1 << nodesCount); conf++) {
for (int node = 0; node < nodesCount; node++) {
if (dp[conf][node] == -1) {
continue;
}
for (Edge edge : graph[node]) {
if (conf & (1 << edge.destination)) {
continue;
}
int newConf = conf ^ (1 << edge.destination);
if (dp[conf][node] + edge.cost > dp[newConf][edge.destination]) {
dp[newConf][edge.destination] = dp[conf][node] + edge.cost;
bkt[newConf][edge.destination] = node;
}
}
}
}
}
void BuildAnswerIndices(int nodesCount) {
int ans = -1;
int lastNode = -1;
for (int node = 0; node < nodesCount; node++) {
if (dp[(1 << nodesCount) - 1][node] == 0) {
continue;
}
if (dp[(1 << nodesCount) - 1][node] > ans) {
ans = dp[(1 << nodesCount) - 1][node] ;
lastNode = node;
}
}
int conf = (1 << nodesCount) - 1;
int newNode = lastNode;
while (conf) {
lastNode = newNode;
answerIndices.push_back(nodesNewToInit[lastNode]);
newNode = bkt[conf][lastNode];
conf = conf ^ (1 << lastNode);
}
}
void BuildAnswer() {
int firstNode = answerIndices.back();
fout << str[firstNode];
answerIndices.pop_back();
while (!answerIndices.empty()) {
int secondNode = answerIndices.back();
answerIndices.pop_back();
int overlap = costs[firstNode][secondNode];
int len = str[secondNode].length();
for (int j = overlap; j < len; j++) {
fout << str[secondNode][j];
}
firstNode = secondNode;
}
}
int main() {
fin >> n;
for (int i = 1; i <= n; i++) {
fin >> str[i];
}
BuildCostsMatrix();
int nodesCount = BuildGraph();
BuildDynamicConfiguration(nodesCount);
BuildAnswerIndices(nodesCount);
BuildAnswer();
return 0;
}