Pagini recente » Cod sursa (job #978055) | Cod sursa (job #1298053) | Istoria paginii utilizator/petronela22 | Cod sursa (job #105769) | Cod sursa (job #1587089)
/*#include <fstream>
#include <string>
#include <vector>
using namespace std;
ifstream fin ("1.in");
ofstream fout ("1.out");
int n, D[30010], Cost[20][20], C[20][(1 << 18) + 10], Dad[20][(1 << 18) + 10];
string S[20];
bool F[20];
vector < int > Sol;
int KMP(string &A, string &B)
{
int k = 0;
for (int i = 1; i < A.size(); i ++)
{
while (k && A[i] != A[k]) k = D[k - 1];
if (A[i] == A[k]) k ++;
D[i] = k;
}
k = 0;
for (int i = 0; i < B.size(); i ++)
{
while (k && B[i] != A[k]) k = D[k - 1];
if (B[i] == A[k]) k ++;
}
return k;
}
bool Verif(string &A, string &B)
{
int k = 0;
for (int i = 1; i < A.size(); i ++)
{
while (k && A[i] != A[k]) k = D[k - 1];
if (A[i] == A[k]) k ++;
D[i] = k;
}
k = 0;
for (int i = 0; i < B.size(); i ++)
{
while (k && B[i] != A[k]) k = D[k - 1];
if (B[i] == A[k]) k ++;
if (k == A.size())
{
return true;
}
}
return false;
}
int main()
{
fin >> n;
for (int i = 1; i <= n; i ++) fin >> S[i];
/// Daca se cuprinde vreun cuvant in altul
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
if (i == j || F[i] || F[j]) continue;
if (S[i].size() <= S[j].size())
{
if (Verif(S[i], S[j])) F[i] = true;
}
}
}
/// Elimin cuvintele cuprinse in altele
for (int i = 1; i <= n; i ++)
{
while (F[i] && i <= n)
{
swap(F[i], F[n]);
swap(S[i], S[n]);
n --;
}
}
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
if (i == j) continue;
Cost[i - 1][j - 1] = KMP(S[j], S[i]); /// cel mai lung sufix al cuvantului i care este prefix al cuvantului j
}
}
/// ciclu hamiltonian de cost maxim j find nodul de inceput adaugandul de fiecare data
for (int mask = 0; mask < (1 << n); mask ++)
{
for (int j = 0; j < n; j ++)
{
Dad[j][mask] = -1;
if (mask & (1 << j))
{
for (int k = 0; k < n; k ++)
{
if (mask & (1 << k))
{
if (C[k][mask ^ (1 << j)] + Cost[j][k] > C[j][mask])
{
C[j][mask] = C[k][mask ^ (1 << j)] + Cost[j][k];
Dad[j][mask] = k;
}
}
}
}
}
}
/// Cautam nodul de start
int sum = 0, nod = 0;
for (int i = 0; i < n; i ++)
{
if (C[i][(1 << n) - 1] > sum)
{
sum = C[i][(1 << n) - 1];
nod = i;
}
}
/// Cautam lantul de cost maxim si lungine minima
int mask = (1 << n) - 1, next_nod;
while (nod > -1)
{
Sol.push_back(nod + 1);
next_nod = Dad[nod][mask];
mask -= (1 << nod);
nod = next_nod;
}
for (int i=0;i<Sol.size();i++) fout<<Sol[i]<<' ';
fout<<endl;
/// Afisam solutia
fout << S[Sol.front()];
nod = Sol.front();
for (int i = 1; i < Sol.size(); i ++)
{
int de_unde = Cost[nod - 1][Sol[i] - 1];
//S[Sol[i]].erase(0, de_unde);
fout << S[Sol[i]].substr(de_unde);
nod = Sol[i];
}
fout.close();
return 0;
}
*/
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#define lmax 30010
using namespace std;
int n,st,nr;
int dp[20][lmax*10],path[20][lmax*10];
int urm[lmax],dif[20][20],sol[20];
bool del[20],viz[20][lmax*10];
string s[20];
char ss[lmax];
vector < pair<int,int> > g[20];
int memo(int nod,int mask)
{
if (mask==0) return 0; else
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;
if (y==st && mask!=1<<y) continue;
if (((mask>>(y-1))&1)==1) {
int val=memo(y,mask-(1<<(y-1)))+g[nod][i].second;
if (dp[nod][mask]<val) {
dp[nod][mask]=val; path[nod][mask]=y;
}
}
}
return dp[nod][mask];
}
int nrbit(int x) { return (x&(x-1)); }
void findpath(int nod,int mask)
{
if (nrbit(mask)==0) return; else
{
int x=path[nod][mask];
nr++; sol[nr]=x;
findpath(x,mask-(1<<(x-1)));
}
}
int main()
{
freopen("adn.in","r",stdin);
freopen("adn.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%s",ss); s[i]=ss; s[i].insert(0," ");
}
for (int i=1;i<=n;i++)
if (!del[i]) {
for (int j=1;j<=n;j++)
if (i!=j && !del[j]) {
urm[1]=0; int k=0;
for (int l=2;l<(int)s[i].size();l++) {
while (k>0 && s[i][l]!=s[i][k+1]) k=urm[k];
if (s[i][l]==s[i][k+1]) k++;
urm[l]=k;
}
bool ok=false; k=0;
for (int l=1;l<(int)s[j].size();l++) {
while (k>0 && s[j][l]!=s[i][k+1]) k=urm[k];
if (s[j][l]==s[i][k+1]) k++;
if (k==s[i].size()-1) { ok=true; break; }
}
if (ok) { del[i]=true; break; }
}
}
int m=0;
for (int i=1;i<=n;i++)
if (!del[i]) { m++; s[m]=s[i]; }
n=m;
for (int i=1;i<=n;i++) {
for (int j=1;j<=n;j++)
if (i!=j) {
/*verific daca prefixul lui s[i] se regaseste ca sufix in s[j]; */
urm[1]=0; int k=0;
for (int l=2;l<(int)s[i].size();l++) {
while (k>0 && s[i][l]!=s[i][k+1]) k=urm[k];
if (s[i][l]==s[i][k+1]) k++;
urm[l]=k;
}
k=0;
for (int l=1;l<(int)s[j].size();l++) {
while (k>0 && s[j][l]!=s[i][k+1]) k=urm[k];
if (s[j][l]==s[i][k+1]) k++;
if (k==s[i].size()-1) k=urm[k];
}
g[i].push_back(make_pair(j,k)); dif[i][j]=k;
}
}
for (int i=1;i<=n;i++) s[i].erase(s[i].begin());
int maxx=(1<<n)-1,best=0,ind=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=maxx;j++)
dp[i][j]=-1;
for (int i=1;i<=n;i++) {
st=i;
for (int j=0;j<g[i].size();j++) {
int val=memo(g[i][j].first,maxx-(1<<(g[i][j].first-1)))+g[i][j].second;
if (dp[i][maxx]<val) {
dp[i][maxx]=val; path[i][maxx]=g[i][j].first;
}
}
}
for (int i=1;i<=n;i++)
if (dp[i][maxx]>best) {
ind=i; best=dp[i][maxx];
}
nr=1; sol[nr]=ind;
findpath(ind,maxx);
for (int i=1;i<nr;i++) {
int y=dif[sol[i+1]][sol[i]];
for (int j=0;j<s[sol[i]].size()-y;j++) printf("%c",s[sol[i]][j]);
}
//cout<<s[sol[1]];
printf("\n");
return 0;
}