Cod sursa(job #395256)

Utilizator deiosxHalalai Tudor Andrei deiosx Data 12 februarie 2010 17:28:39
Problema Datorii Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.45 kb
#include <cstdio> 
#include <cstring> 
#define MAX_N 18 
#define MAX_L 30001 
#define INF 0x3f3f3f3f 
int N, Sz[MAX_N], M; 
char S[MAX_N][MAX_L]; 
int C[MAX_N][MAX_N], pi[MAX_N]; 
int A[1 << MAX_N][MAX_N], T[MAX_N]; 
struct adn 
{ 

int x, y; 
} Ant[1 << MAX_N][MAX_N]; 
void citire() 
{ 
scanf("%d",&N); 
  
 
    
for(int i = 0; i < N; ++i) 
    
{ 
        
scanf(" %s",S[i]+1); 
        
Sz[i] = strlen(S[i]+1); 
    
} 
} 
 
 
void make_prefix(char A[MAX_N], int N) 
{ 
   
pi[1] = 0; 
   
for(int i = 2, q = 0; i <= N; ++i) 
    
{ 
        
while(q && A[q+1] != A[i]) 
            
q = pi[q]; 
         
 
        
if(A[q+1] == A[i]) 
            
 
         
 
        
pi[i] = q; 
    
} 
} 
 
 
int search(char A[MAX_N], int N, char B[MAX_N], int M) 
{ 
    
make_prefix(A, N); 
    
 
    
for(int i = 1, q = 0; i <= M; ++i) 
    
{ 
        
while(q && A[q+1] != B[i]) 
            
q = pi[q]; 
         
 
        
if(A[q+1] == B[i]) 
            
++q; 
         
 
        
if(i == M) 
            
return q; 
         
 
        
if(q == N) 
            
return -1; 
    
} 
    
return 0; 
} 
 
 
void pre() 
{ 
    
for(int i = 0; i < N; ++i) 
        
for(int j = i; j < N; ++j) 
        
{ 
            
C[i][j] = search(S[j], Sz[j], S[i], Sz[i]); 
            
C[j][i] = search(S[i], Sz[i], S[j], Sz[j]); 
        
} 
} 
 

void solve() 
{ 
    
M = 1 << N; 
     
 
    
for(int i = 0; i < M; ++i) 
        
for(int j = 0; j < N; ++j) 
            
A[i][j] = INF; 
     
 
    
for(int i = 0; i < N; ++i) 
        
A[(1 << i)][i] = Sz[i]; 
         
 
    
for(int i = 1; i < M; ++i) 
        
for(int j = 0; j < N; ++j) 
        
{ 
            
if(A[i][j] == INF) continue; 
             
 
            
for(int k = 0; k < N; ++k) 
            
{ 
                
if(i & (1 << k)) continue; 
                
if(j == k) continue; 
                
int _i = i + (1 << k); 
                
if(C[j][k] == -1) 
                
{ 
                    
if(A[_i][j] > A[i][j]) 
                    
{ 
                        
A[_i][j] = A[i][j]; 
                        
Ant[_i][j].x = i; 
                        
Ant[_i][j].y = j; 
                    
} 
                
} 
                     
 
                
else
                    
if(A[_i][k] > A[i][j] + Sz[k] - C[j][k]) 
                    
{ 
                        
A[_i][k] = A[i][j] + Sz[k] - C[j][k]; 
                        
Ant[_i][k].x = i; 
                        
Ant[_i][k].y = j; 
                    
} 
            
} 
        
} 
} 

 
void reconst() 
{ 
    
int x = M-1, y = 0, Sol = A[M-1][0], nr = N; 
     
 
    
for(int i = 1; i < N; ++i) 
        
if(Sol > A[M-1][i]) 
            
Sol = A[M-1][i], 
            
y = i; 
     
 
    
while(x) 
    
{ 
        
T[--nr] = y; 
        
int auxx = Ant[x][y].x, auxy = Ant[x][y].y; 
        
x = auxx; 
        
y = auxy; 
    
} 
 
 
    
for(int i = 1; i <= Sz[T[0]]; ++i) 
        
printf("%c",S[T[0]][i]); 
    
for(int i = 1; i < N; ++i) 
        
for(int j = C[T[i-1]][T[i]]+1; j <= Sz[T[i]]; ++j) 
            
printf("%c", S[T[i]][j]); 
} 
 
 
int main() 
{ 
    
freopen("adn.in","rt",stdin); 
    
freopen("adn.out","wt",stdout); 
     
 
    
citire(); 
    
pre(); 
    
solve(); 
    
reconst(); 
}