Pagini recente » Cod sursa (job #806827) | Cod sursa (job #266664) | Cod sursa (job #1010951) | Cod sursa (job #1492666) | Cod sursa (job #1586619)
#include <stdio.h>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#define lmax 30010
#define inf 80000
using namespace std;
int n,startp,nr,maxx;
int dp[20][lmax*10],path[20][lmax*10];
int urm[lmax],dif[20][20],sol[20];
bool viz[20][lmax*10];
char ss[lmax];
bool fr[20];
string s[20];
vector < pair< int,int > > g[20];
int memo(int nod,int mask)
{
if (mask==0) return 0;
if (viz[nod][mask]) return dp[nod][mask];
viz[nod][mask]=true;
for (unsigned int i=0;i<g[nod].size();i++) {
int y=g[nod][i].first-1;
if (y+1==startp && mask!=1<<y) continue;
if (((mask>>y)&1)==1) {
int val=memo(y+1,mask-(1<<y));
if (dp[nod][mask]>val) {
path[nod][mask]=y+1; dp[nod][mask]=val;
}
}
}
return dp[nod][mask];
}
bool nrbit(int x)
{
return (x&(x-1));
}
void findpath(int x,int mask)
{
if (nrbit(mask)==0) return; else
{
int y=path[x][mask];
nr++; sol[nr]=y;
findpath(y,mask-(1<<(y-1)));
}
}
int countpath(int x,int maxx)
{
int l=0; nr=1; sol[nr]=x;
findpath(x,maxx);
for (int i=1;i<nr;i++) {
l=l+(s[sol[i]].size()-1-dif[sol[i]][sol[i+1]]);
}
return l+s[sol[nr]].size()-1;
}
int main()
{
freopen("adn.in","r",stdin);
freopen("adn.out","w",stdout);
scanf("%d ",&n);
for (int i=1;i<=n;i++) {
gets(ss); s[i]=ss; s[i].insert(0," ");
}
for (int i=1;i<=n;i++) {
if (fr[i]) continue;
for (int j=1;j<=n;j++)
if (i!=j && s[i].size()>=s[j].size() && fr[j]==false) {
urm[1]=0; int k=0;
for (int l=2;l<=(int)s[j].size()-1;l++) {
while (k>0 && s[j][l]!=s[j][k+1]) k=urm[k];
if (s[j][l]==s[j][k+1]) k++;
urm[l]=k;
}
bool ok=false; k=0;
for (int l=1;l<=(int)s[i].size()-1;l++) {
while (k>0 && s[i][l]!=s[j][k+1]) k=urm[k];
if (s[i][l]==s[j][k+1]) k++;
if (k==s[j].size()-1) { ok=true; break; }
}
if (ok) fr[j]=true;
}
}
for (int i=1;i<=n;i++)
if (!fr[i]) {
for (int j=1;j<=n;j++)
if (i!=j && !fr[j]) {
urm[1]=0; int k=0;
for (int l=2;l<=(int)s[j].size()-1;l++) {
while (k>0 && s[j][l]!=s[j][k+1]) k=urm[k];
if (s[j][l]==s[j][k+1]) k++;
urm[l]=k;
}
k=0;
for (int l=1;l<=(int)s[i].size()-1;l++) {
while (k>0 && s[i][l]!=s[j][k+1]) k=urm[k];
if (s[i][l]==s[j][k+1]) k++;
if (k==s[j].size()-1) k=urm[k];
}
g[j].push_back(make_pair(i,s[j].size()-k)); dif[i][j]=k;
}
}
int maxx=(1<<n)-1,best=2e9,nrnod=0;
for (int i=1;i<=n;i++)
if (fr[i]) maxx=maxx-(1<<(i-1));
for (startp=1;startp<=n;startp++)
if (!fr[startp])
{
for (int i=1;i<=n;i++)
for (int k=1;k<=maxx;k++)
dp[i][k]=2e9,viz[i][k]=false,path[i][k]=0;
for (unsigned int i=0;i<g[startp].size();i++) {
int val=memo(g[startp][i].first,maxx-(1<<(g[startp][i].first-1)))+g[startp][i].second;
if (dp[startp][maxx]>val) {
path[startp][maxx]=g[startp][i].first; dp[startp][maxx]=val;
}
}
int dist=countpath(startp,maxx);
if (dist<best) { best=dist; nrnod=startp; }
}
startp=nrnod;
for (int i=1;i<=n;i++)
for (int k=1;k<=maxx;k++)
dp[i][k]=2e9,viz[i][k]=false,path[i][k]=0;
for (unsigned int i=0;i<g[startp].size();i++) {
int val=memo(g[startp][i].first,maxx-(1<<(g[startp][i].first-1)))+g[startp][i].second;
if (dp[startp][maxx]>val) {
path[startp][maxx]=g[startp][i].first; dp[startp][maxx]=val;
}
}
for (int i=1;i<=n;i++) s[i].erase(s[i].begin());
nr=1; sol[1]=startp; findpath(startp,maxx);
for (int i=1;i<nr;i++) {
int l=dif[sol[i]][sol[i+1]];
for (int j=0;j<(int)s[sol[i]].size()-l;j++) printf("%c",s[sol[i]][j]);
}
cout<<s[sol[nr]]<<'\n';
return 0;
}