算是比较基本的题,不忍直视的搓代码,string乱搞后惨不忍睹,调了好久终于AC,代码能力弱成渣。
做法:给你的一些串中,你先暴力去掉一些无用的子串, 比方有aaaa 和aa,那aa就没用了,去掉
然后从下往上放字符串(注意方向,为了输出字典序最小),我的val[i][j]表示串i在下,串j在上所增加的str[i]的前缀长度 如 aabb bbcccc, 那前缀为aa,长度为2
然后dfs搜出解。string用得太逗比了,这里用char字符串也还可以,写得好就很方便。
附上刚刚AC的代码和以前AC的代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> using namespace std; string str[17]; int n; bool ok(const string &a, const string &b) { int sz = max<int>(0, b.size()-a.size()); int i, j, cur; for(i = 0; i < sz; i++) { cur = i; for(j = 0; j < (int)a.size() && cur < (int)b.size()&& a[j] == b[cur]; j++, cur++); if(j == (int)a.size()) return 1; } return 0; } int cal(const string &a , const string &b) { int i, j, cur; int ret = b.size(); for(i = 0; i < (int)b.size(); i++) { cur = i; for(j = 0; j < (int)a.size() && cur < (int)b.size() && a[j] == b[cur]; j++, cur++); if(cur == (int)b.size()) ret = min<int>(ret, i); } return ret; } int val[17][17]; int dp[17][1<<17]; void out(int pos, int st) { if(st == (st&-st)) { //cout << "nice" << endl; cout << str[pos]; return; } int j, cur = -1; string tp = "Z"; int ans = -1; for(j = 0; j < n; j++) if(j != pos && (st&(1<<j))) { // cout << "j " << j << endl; if(dp[j][st^(1<<pos)] + val[j][pos] == dp[pos][st]) { // cout << "first " << str[pos].size()-val[j][pos]; string res = str[j].substr(str[pos].size()-val[j][pos], str[j].size()); // cout << "res~~~~" << res << endl; if(res < tp) { tp = res; cur = j; ans = val[j][pos]; } } } // cout << "ans = " << ans << endl; //cout << "~~~~~~~~~~~~~" << endl; cout << str[pos].substr(0, val[cur][pos]); //cout << "cur~~~" <<cur<< endl; out(cur, st^(1<<pos)); } int full; int main() { int i, j, k, cas, ca = 1; cin >> cas; while(cas--) { cin >> n; for(i = 0; i < n; i++) cin >> str[i]; int m = 0; for(i = 0; i < n; i++) { for(j = 0; j < n; j++)if(j != i) if(ok(str[i], str[j])) break; if(j == n) str[m++] = str[i]; } n = m; full = (1<<n)-1; // for(i = 0; i < n; i++) // cout << str[i] << endl; for(i = 0; i < n; i++) for(j = 0; j < n; j++) if(i != j) { val[i][j] = cal(str[i], str[j]); // printf("val[%d][%d] = %d\n", i, j, val[i][j]); } for(i = 0; i < n; i++) for(j = 0; j < (1<<n); j++) dp[i][j] = -1; for(i = 0; i < n; i++) dp[i][1<<i] = str[i].size(); for(j = 0; j < (1<<n); j++) for(i = 0; i < n; i++) if(~dp[i][j]) { for(k = 0; k < n; k++) if(!(j&(1<<k))) { int inc = dp[i][j] + val[i][k]; //cout << inc << endl; if(dp[k][j|(1<<k)] == -1 || dp[k][j|(1<<k)] > inc) { dp[k][j|(1<<k)] = inc; } } } //for(i = 0; i < n; i++) // cout << "i = " << dp[i][full] << endl; int pos = 0; // cout << (str[1] < str[2]) << endl; // cout << n <<"~~~" << endl; for(i = 1; i < n; i++) if( dp[i][full] < dp[pos][full] || (dp[i][full] == dp[pos][full] && str[i] < str[pos])) { pos = i; // cout << "update" << pos << endl; } cout << "Case " << ca++ << ": "; // cout << "pos = " << pos << endl; // cout << "~~~" << dp[pos][full] << endl; //cout << full << endl; out(pos, full); cout << endl; } return 0; } /* 1 10 TTTT TT T T T GCGCG CCCC C C C */
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int inf = 1e9; struct node { int len; char s[103]; void in() { scanf("%s", s); len = strlen(s); } }p[16]; int n; int cnt[16][16]; int two[18]; int dp[15][33333]; int Log[33333]; int f[101]; inline void getfail(char *s, int &la) { int i, j = 0; f[0] = f[1] = 0; for(i = 1; i < la; i++) { while(j && s[i] != s[j]) j = f[j]; if(s[i] == s[j]) j++; f[i+1] = j; } } inline bool kmp(char *s, char *t, int &la, int &lb) { int i, j = 0; getfail(t, lb); for(i = 0; i < la; i++) { while(j && s[i] != t[j]) j = f[j]; if(s[i] == t[j]) j++; if(j == lb) return 1; } return 0; } inline bool ok(int &x, int &y) { int i, j; for(i = 0; i < p[x].len; i++) { for(j = 0; j < p[y].len && i+j < p[x].len && p[x].s[i+j] == p[y].s[j]; j++); if(j == p[y].len) return 1; } return 0; } bool cmp1(const node &a, const node &b) { return a.len > b.len; } bool cmp2(const node &a, const node &b) { return strcmp(a.s, b.s) < 0; } inline void out(int pos, int st) { if(!st) { puts(p[pos].s); return; } int i; int ans = -1, idx; for(int x = ~two[n]&st; x; x -= x&-x) { i = Log[x&-x]; int inc = dp[i][st^two[i]] + p[pos].len - cnt[pos][i]; if(ans == -1 || ans > inc || (ans == inc && strcmp(&p[i].s[cnt[pos][i]],&p[idx].s[cnt[pos][idx]]) < 0) ) { ans = inc; idx = i; } } int end = p[pos].len - cnt[pos][idx]; for(i = 0; i < end; i++) printf("%c", p[pos].s[i]); out(idx, st^two[idx]); } int main() { int i, j, x, y, cas; two[0] = 1; Log[0] = -1; for(i = 1; i <= 16; i++) two[i] = two[i-1] << 1; for(i = 1; i < two[15]; i++) Log[i] = Log[i>>1] + 1; scanf("%d", &cas); for(int ca = 1; ca <= cas; ca++) { scanf("%d", &n); for(i = 0; i < n; i++) p[i].in(); sort(p, p+n, cmp1); int m = 1; for(i = 1; i < n; i++) { getfail(p[i].s, p[i].len); for(j = 0; j < m; j++) if(kmp(p[j].s, p[i].s, p[j].len, p[i].len)) break; if(j == m) { p[m++] = p[i]; } } n = m; sort(p, p+n, cmp2); for(i = 0; i < n; i++) { for(j = 0; j < n; j++) if(i != j){ cnt[i][j] = 0; for(x = 0; x < p[i].len; x++) { int tp = 0; for(y = 0; y < p[j].len && x+y < p[i].len && p[i].s[x+y] == p[j].s[y]; y++) tp++; if(x+y == p[i].len) cnt[i][j] = max(cnt[i][j], tp); } } } printf("Case %d: ", ca); for(i = 0; i < n; i++) for(j = 0; j < two[n]; j++) dp[i][j] = -1; int ans = -1, pos; for(i = 0; i < n; i++) dp[i][0] = p[i].len; for(j = 0; j < two[n]; j++) { for(i = 0; i < n; i++) if(~dp[i][j]){ for(int xx = (two[n+1]-1)^(~two[n]&j); xx; xx -= xx&-xx) { x = Log[xx&-xx]; if(i == x) continue; int inc = dp[i][j] + p[x].len - cnt[x][i]; if(dp[x][j|two[i]] == -1 || dp[x][j|two[i]] > inc) { dp[x][j|two[i]] = inc; } } } } for(i = 0; i < n; i++) { if(ans == -1 || ans > dp[i][(two[n]-1)^two[i]]) { ans = dp[i][(two[n]-1)^two[i]]; pos = i; } } out(pos, (two[n]-1)^two[pos]); } }