Description
给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。
Sample Input
2
ABCD
BCDABC
Sample Output
ABCDABC
考虑状压DP。
先去一下重。
然后预处理两个串的最大重叠。
然后就是字典序的大小,于是你每次都要back回去。。。
有点麻烦。
strcmp返回大于0的值表示大于。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
int f[13][4096], last[13][4096];
int bs[13][13], len[13];
char ss[13][51], qq[31][51], hh[610], ll[610];
bool check(int a, int b, int c, int d) {
int tp1 = 0;
for(int i = len[a]; i; i--) hh[++tp1] = qq[a][i];
int pos = a, now = b;
while(pos) {
int u = last[pos][now];
for(int j = len[u] - bs[u][pos]; j; j--) hh[++tp1] = qq[u][j];
now ^= 1 << pos - 1, pos = u;
} for(int i = 1; i <= tp1 / 2; i++) swap(hh[i], hh[tp1 - i + 1]);
hh[tp1 + 1] = '\0';
int tp2 = 0;
for(int i = len[a]; i; i--) ll[++tp2] = qq[a][i];
for(int i = len[c] - bs[c][a]; i; i--) ll[++tp2] = qq[c][i];
pos = c, now = d;
while(pos) {
int u = last[pos][now];
for(int j = len[u] - bs[u][pos]; j; j--) ll[++tp2] = qq[u][j];
now ^= 1 << pos - 1, pos = u;
} for(int i = 1; i <= tp2 / 2; i++) swap(ll[i], ll[tp2 - i + 1]);
ll[tp2 + 1] = '\0';
if(strcmp(hh + 1, ll + 1) > 0) return 1;
return 0;
}
int main() {
int n = read(), tp = 0;
for(int i = 1; i <= n; i++) scanf("%s", ss[i] + 1);
for(int i = 1; i <= n; i++) {
bool bk = 0; int len = strlen(ss[i] + 1);
for(int j = 1; j <= n; j++) if(i != j){
for(int k = 1; k <= strlen(ss[j] + 1); k++) {
bool hh = 0;
for(int u = 1; u <= len; u++) {
if(ss[j][u + k - 1] != ss[i][u]) {hh = 1; break;}
} if(!hh) {bk = 1; break;}
} if(bk) break;
} if(!bk) {
++tp;
for(int j = 1; j <= strlen(ss[i] + 1); j++) qq[tp][j] = ss[i][j];
}
} n = tp;
if(n == 0) {
printf("%s\n", ss[1] + 1);
return 0;
}
for(int i = 1; i <= n; i++) {
len[i] = strlen(qq[i] + 1);
for(int j = 1; j <= n; j++) if(i != j){
int yy = strlen(qq[j] + 1);
for(int k = 1; k <= len[i]; k++) {
int uu = yy + 1;
for(int u = 1; u <= yy; u++) {
if(qq[i][k + u - 1] != qq[j][u]) {uu = u; break;}
} uu--;
if(k + uu - 1 == len[i]) bs[i][j] = _max(bs[i][j], uu);
}
}
} memset(f, -1, sizeof(f));
for(int i = 1; i <= n; i++) f[i][1 << i - 1] = len[i];
for(int i = 1; i < 2046; i++) {
for(int j = 1; j <= n; j++) if(f[j][i] != -1){
for(int k = 1; k <= n; k++) if(!(i >> (k - 1) & 1)){
if(f[k][i ^ (1 << k - 1)] == -1)
f[k][i ^ (1 << k - 1)] = f[j][i] + len[k] - bs[j][k], last[k][i ^ (1 << k - 1)] = j;
else if(f[k][i ^ (1 << k - 1)] > f[j][i] + len[k] - bs[j][k]){
f[k][i ^ (1 << k - 1)] = f[j][i] + len[k] - bs[j][k];
last[k][i ^ (1 << k - 1)] = j;
} else if(f[k][i ^ (1 << k - 1)] == f[j][i] + len[k] - bs[j][k]) {
if(check(k, i ^ (1 << k - 1), j, i)) last[k][i ^ (1 << k - 1)] = j;
}
}
}
}
for(int i = 2046; i < (1 << n); i++) {
for(int j = 1; j <= n; j++) if(f[j][i] != -1){
for(int k = 1; k <= n; k++) if(!(i >> (k - 1) & 1)){
if(f[k][i ^ (1 << k - 1)] == -1)
f[k][i ^ (1 << k - 1)] = f[j][i] + len[k] - bs[j][k], last[k][i ^ (1 << k - 1)] = j;
else if(f[k][i ^ (1 << k - 1)] > f[j][i] + len[k] - bs[j][k]){
f[k][i ^ (1 << k - 1)] = f[j][i] + len[k] - bs[j][k];
last[k][i ^ (1 << k - 1)] = j;
} else if(f[k][i ^ (1 << k - 1)] == f[j][i] + len[k] - bs[j][k]) {
if(check(k, i ^ (1 << k - 1), j, i)) last[k][i ^ (1 << k - 1)] = j;
}
}
}
}
int ans = 999999999;
for(int i = 1; i <= n; i++) {
if(f[i][(1 << n) - 1] != -1 && f[i][(1 << n) - 1] < ans) ans = f[i][(1 << n) - 1];
} memset(hh, 0, sizeof(hh)), memset(ll, 0, sizeof(ll));
int g;
for(int i = 1; i <= n; i++) if(f[i][(1 << n) - 1] == ans){
int pos = i, now = (1 << n) - 1;
int tp = 0; for(int j = len[i]; j; j--) ll[++tp] = qq[i][j];
while(pos) {
int u = last[pos][now];
for(int j = len[u] - bs[u][pos]; j; j--) ll[++tp] = qq[u][j];
now ^= 1 << pos - 1, pos = u;
} ll[ans + 1] = '\0', hh[ans + 1] = '\0';
for(int j = 1; j <= ans / 2; j++) swap(ll[j], ll[ans - j + 1]);
if(hh[1] == 0) {
for(int j = 1; j <= ans; j++) hh[j] = ll[j]; g = i;
} else if(strcmp(hh + 1, ll + 1) > 0) swap(hh, ll), g = i;
} int o = strlen(hh + 1);
printf("%s\n", hh + 1);
return 0;
}