2 2 1110 0111 101 1001 0 0
5
ac自动机处理合并费用,状态压缩dp得出答案。
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int size = 2; const char base = '0'; const int maxn = 1005; int n, m; class tire { public: tire *next[size], *fail; int cnt, virus, deep, id; tire(){ cnt = -1; id = virus = 0; fail = NULL; memset(next, 0, sizeof(next)); } }; class ac { private: tire *root, *node[15]; int map[15][15], dp[1 << 11][11], tot,vis[60005]; char s[maxn]; public: ac(){ memset(map, 0, sizeof(map)); root = new tire; tot = 0; } void clear(){ memset(map, 0, sizeof(map)); root = new tire; tot = 0; } void insert(int x) { scanf("%s", s); tire *j = root; for (int i = 0, k; s[i]; i++) { k = s[i] - base; if (!j->next[k]) { j->next[k] = new tire; j->next[k]->id = ++tot; } j = j->next[k]; } if (x < 0) j->virus = 1; else { node[x] = j; j->cnt = x; map[x][x] = strlen(s); } } void getfail() { root->fail = root; queue<tire *> p; for (int i = 0; i < size; i++) { if (root->next[i]) { root->next[i]->fail = root; p.push(root->next[i]); } else root->next[i] = root; } tire *q, *k; while (!p.empty()) { q = p.front(); p.pop(); k = q->fail; for (int i = 0; i < size; i++) if (q->next[i]) { q->next[i]->fail = k->next[i]; p.push(q->next[i]); } else q->next[i] = k->next[i]; } } void getmap() { queue<tire *> p; tire *q, *k; for (int i = 0; i < n; i++) { p.push(node[i]); node[i]->deep = 0; memset(vis, 0, sizeof(vis)); vis[node[i]->id] = 1; while (!p.empty()) { q = p.front(); p.pop(); for (int j = 0; j < size; j++) if (!vis[q->next[j]->id]) { k = q->next[j]; k->deep = q->deep + 1; if (k->cnt >= 0 && !map[i][k->cnt]) map[i][k->cnt] = k->deep; if (!k->virus){ p.push(k); vis[k->id] = 1; } } } } } int work_out() { getfail(); getmap(); memset(dp, 1, sizeof(dp)); for (int i = 0; i < n; i++) dp[1 << i][i] = map[i][i]; for (int i = 1; i < (1 << n); i++) { for (int j = 0; j < n; j++) if (i&(1 << j)) for (int k = 0; k < n;k++) if ((i&(1 << k))==0) if (map[j][k]) { dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + map[j][k]); } } int ans = 0x7FFFFFFF; for (int i = 0; i < n; i++) ans = min(ans, dp[(1 << n) - 1][i]); return ans; } }f; int main() { while (scanf("%d%d", &n, &m), n + m) { f.clear(); for (int i = 0; i < n; i++) f.insert(i); while (m--) f.insert(-1); printf("%d\n", f.work_out()); } }