【HDOJ】3828 A + B problem
显然需要贪心,重叠越长越好,这样最终的串长尽可能短。
需要注意的是,不要考虑中间结果,显然是个状态dp。
先做预处理去重,然后求任意一对串的公共长度。
1 /* 3828 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 45 const int INF = 0x3f3f3f3f; 46 const int maxl = 70; 47 const int maxn = 16; 48 const int mod = 1000000009; 49 __int64 a[maxn]; 50 char word[maxn][maxl]; 51 string sw[maxn]; 52 int nxt[maxl]; 53 int Len[maxn]; 54 bool visit[maxn]; 55 int dp[1<<16][16]; 56 int M[16][16]; 57 int n; 58 59 void f(char *s, __int64 x) { 60 int l = 0; 61 while (x) { 62 s[l] = (x & 1) + '0'; 63 ++l; 64 x >>= 1; 65 } 66 s[l] = '\0'; 67 reverse(s, s+l); 68 } 69 70 void getnext(char *s) { 71 int i = 0, j = -1; 72 int l = strlen(s); 73 74 nxt[0] = -1; 75 while (i < l) { 76 if (j==-1 || s[i]==s[j]) { 77 ++i; 78 ++j; 79 nxt[i] = j; 80 } else { 81 j = nxt[j]; 82 } 83 } 84 } 85 86 bool match(char *d, char *s, int ld, int ls) { 87 int i = 0, j = 0; 88 89 while (i < ld) { 90 if (d[i] == s[j]) { 91 ++i; 92 ++j; 93 } else { 94 j = nxt[j]; 95 if (j == -1) { 96 j = 0; 97 ++i; 98 } 99 } 100 if (j == ls) 101 return true; 102 } 103 104 return false; 105 } 106 107 void cover() { 108 memset(visit, false, sizeof(visit)); 109 rep(i, 0, n) { 110 getnext(word[i]); 111 rep(j, 0, n) { 112 if (i == j) 113 continue; 114 if (match(word[j], word[i], Len[j], Len[i])) { 115 visit[i] = true; 116 break; 117 } 118 } 119 } 120 121 int nn = 0; 122 rep(i, 0, n) { 123 if (!visit[i]) { 124 strcpy(word[nn], word[i]); 125 Len[nn] = strlen(word[nn]); 126 ++nn; 127 } 128 } 129 n = nn; 130 } 131 132 bool judge(int l, char *sa, char *sb) { 133 rep(i, 0, l) { 134 if (sa[i] != sb[i]) 135 return false; 136 } 137 return true; 138 } 139 140 int LongFix(int a, int b) { 141 per(l, 1, Len[a]) { 142 if (Len[b]>=l && judge(l, word[a]+Len[a]-l, word[b])) 143 return l; 144 } 145 146 return 0; 147 } 148 149 void calc() { 150 rep(i, 0, n) { 151 rep(j, 0, n) { 152 if (i == j) { 153 M[i][j] = Len[i]; 154 continue; 155 } 156 M[i][j] = LongFix(i, j); 157 } 158 } 159 } 160 161 void solve() { 162 sort(a, a+n); 163 n = unique(a, a+n) - a; 164 rep(i, 0, n) { 165 f(word[i], a[i]); 166 Len[i] = strlen(word[i]); 167 } 168 cover(); 169 calc(); 170 171 int mst = 1 << n; 172 173 memset(dp, INF, sizeof(dp)); 174 rep(i, 0, n) 175 dp[1<<i][i] = Len[i]; 176 177 rep(i, 0, mst) { 178 rep(j, 0, n) { 179 if (dp[i][j]==INF || (i&(1<<j))==0) 180 continue; 181 182 rep(k, 0, n) { 183 if (i & (1<<k)) 184 continue; 185 186 int nst = i | (1<<k); 187 dp[nst][k] = min(dp[nst][k], dp[i][j]+Len[k]-M[k][j]); 188 } 189 } 190 } 191 192 rep(i, 0, n) 193 sw[i] = string(word[i]); 194 195 int st = mst - 1; 196 int p = -1; 197 198 string str = ""; 199 while (1) { 200 int mn = INF, v; 201 string tstr, mnstr; 202 203 rep(i, 0, n) { 204 if ((st & (1<<i)) == 0) 205 continue; 206 207 int tmp = dp[st][i]; 208 if (p >= 0) { 209 tmp -= M[p][i]; 210 tstr = sw[i].substr(M[p][i]); 211 } else { 212 tstr = sw[i]; 213 } 214 215 if (tmp<mn || (tmp==mn && tstr<mnstr)) { 216 mn = tmp; 217 mnstr = tstr; 218 v = i; 219 } 220 } 221 222 str += mnstr; 223 p = v; 224 st ^= (1 << v); 225 if (st == 0) 226 break; 227 } 228 229 int length = str.length(), base = 1; 230 __int64 ans = 0; 231 232 per(i, 0, length) { 233 if (str[i] == '1') 234 ans = (ans + base) % mod; 235 base = (base + base) % mod; 236 } 237 238 printf("%I64d\n", ans); 239 } 240 241 int main() { 242 ios::sync_with_stdio(false); 243 #ifndef ONLINE_JUDGE 244 freopen("data.in", "r", stdin); 245 freopen("data.out", "w", stdout); 246 #endif 247 248 while (cin >> n) { 249 rep(i, 0, n) 250 cin >> a[i]; 251 solve(); 252 } 253 254 #ifndef ONLINE_JUDGE 255 printf("time = %d.\n", (int)clock()); 256 #endif 257 258 return 0; 259 }