Pagini recente » Cod sursa (job #3329603) | Cod sursa (job #3307031) | Cod sursa (job #3319071) | Cod sursa (job #3353297) | Cod sursa (job #3345777)
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops,fast-math,O3")
#pragma GCC target("avx,avx2,fma")
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
const int NMAX=18,PMAX=(1<<NMAX),MOD=1e9+7,BASE=27,LENMAX=3e4;
int n,i,j,h[NMAX+5][LENMAX+5],p[LENMAX+5],l[NMAX+5][NMAX+5],val[NMAX+5];
int mask,auxmask,lsb,nr,v[NMAX+5],bit1,bit2,final_mask,ans_mask,ans_last,ans_len=1e9;
string s[NMAX+5];
vector <int> sol;
struct elem{
int prev,len;}dp[PMAX+5][NMAX+2];
int longest_suffix(int i, int j)
{
int hash1,hash2;
for (int len=min(s[i].size(),s[j].size()); len>=1; len--)
{
hash2=h[j][len-1];
hash1=h[i][s[i].size()-1];
if (s[i].size()-len>0)
hash1=(hash1-h[i][s[i].size()-1-len])%MOD;
if (hash1<MOD)
hash1+=MOD;
hash2=1LL*hash2*p[s[i].size()-len]%MOD;
if (hash1==hash2)
return len;
}
return 0;
}
bool verif(int i, int j)
{
if (s[i].size()>s[j].size())
return false;
int hash1,hash2;
for (int k=0; k<=s[j].size()-s[i].size(); k++)
{
hash2=h[j][k+s[i].size()-1];
if (k>0)
hash2=(hash2-h[j][k-1])%MOD;
if (hash2<0)
hash2+=MOD;
hash1=h[i][s[i].size()-1];
hash1=1LL*hash1*p[k]%MOD;
if (hash1==hash2)
return true;
}
return false;
}
bool verif_mask(int mask)
{
int val=(mask)&(mask-1);
return val!=0;
}
void init(int mask ,int bit)
{
if (dp[mask][bit].prev==0)
{
dp[mask][bit].prev=-1;
dp[mask][bit].len=1e9;
}
}
int main()
{
ios_base::sync_with_stdio(false);
fin.tie(nullptr); fout.tie(nullptr);
fin>>n;
for (i=1; i<=n; i++)
fin>>s[i];
p[0]=1;
for (i=1; i<=LENMAX; i++)
p[i]=1LL*BASE*p[i-1]%MOD;
for (i=1; i<=n; i++)
{
for (j=0; j<s[i].size(); j++)
{
h[i][j]=1LL*p[j]*(s[i][j]-'A'+1)%MOD;
if (j>0)
h[i][j]=(h[i][j]+h[i][j-1])%MOD;
}
}
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
l[i][j]=longest_suffix(i,j);
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
if (verif(i,j))
val[j-1]+=(1<<(i-1));
for (i=0; i<n; i++)
{
dp[1<<i][i].len=s[i+1].size();
dp[1<<i][i].prev=-1;
}
for (mask=1; mask<(1<<n); mask++)
{
if (verif_mask(mask))
{
auxmask=mask; nr=0; final_mask=0;
while (auxmask)
{
lsb=(auxmask)&(-auxmask);
v[++nr]=log2(lsb);
auxmask-=lsb;
final_mask|=val[v[nr]];
}
for (i=1; i<=nr; i++)
for (j=i+1; j<=nr; j++)
{
bit1=v[i]; bit2=v[j];
init(mask,bit1);
init(mask,bit2);
if (dp[mask][bit1].len>dp[mask-(1<<bit1)][bit2].len+s[bit1+1].size()-l[bit2+1][bit1+1])
{
dp[mask][bit1].len=dp[mask-(1<<bit1)][bit2].len+s[bit1+1].size()-l[bit2+1][bit1+1];
dp[mask][bit1].prev=bit2+1;
}
if (dp[mask][bit2].len>dp[mask-(1<<bit2)][bit1].len+s[bit2+1].size()-l[bit1+1][bit2+1])
{
dp[mask][bit2].len=dp[mask-(1<<bit2)][bit1].len+s[bit2+1].size()-l[bit1+1][bit2+1];
dp[mask][bit2].prev=bit1+1;
}
}
if (final_mask==(1<<n)-1)
{
for (i=1; i<=nr; i++)
{
bit1=v[i];
if (dp[mask][bit1].len<ans_len)
{
ans_len=dp[mask][bit1].len;
ans_mask=mask;
ans_last=bit1;
}
}
}
}
}
while (dp[ans_mask][ans_last].prev!=-1)
{
int new_mask,new_last;
new_mask=ans_mask-(1<<(ans_last));
new_last=dp[ans_mask][ans_last].prev-1;
sol.push_back(ans_last+1);
ans_last=new_last;
ans_mask=new_mask;
}
sol.push_back(ans_last+1);
reverse(sol.begin(),sol.end());
fout<<s[sol[1]];
for (i=1; i<sol.size(); i++)
{
int val=l[sol[i-1]][sol[i]];
for (j=val; j<s[sol[i]].size(); j++)
fout<<s[sol[i]][j];
}
return 0;
}