题目链接:Resource Archiver
解析:n个正常的串,m个病毒串,问包含所有正常串(可重叠)且不包含任何病毒串的字符串的最小长度为多少。
AC自动机 + bfs + 状态压缩DP
用最短路预处理出状态的转移。可以优化很多
AC代码:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; struct Trie{ int next[60010][2], fail[60010], end[60010]; int root, L; int newnode(){ for(int i=0; i<2; i++) next[L][i] = -1; end[L++] = 0; return L-1; } void init(){ L = 0; root = newnode(); } void insert(char buf[], int id){ int len = strlen(buf); int now = root; for(int i=0; i<len; i++){ if(next[now][buf[i] - '0'] == -1) next[now][buf[i] - '0'] = newnode(); now = next[now][buf[i] - '0']; } end[now] = id; } void build(){ queue<int> Q; fail[root] = root; for(int i=0; i<2; i++) if(next[root][i] == -1) next[root][i] = root; else{ fail[ next[root][i] ] = root; Q.push(next[root][i]); } while(!Q.empty()){ int now = Q.front(); Q.pop(); if(end[ fail[now] ] == -1) end[now] = -1; else end[now] |= end[ fail[now] ]; for(int i=0; i<2; i++) if(next[now][i] == -1) next[now][i] = next[ fail[now] ][i]; else{ fail[ next[now][i] ] = next[ fail[now] ][i]; Q.push(next[now][i]); } } } int g[11][11]; int dp[1025][11]; int cnt; int pos[11]; int dis[60010]; void bfs(int k){ queue<int> q; memset(dis, -1, sizeof(dis)); dis[pos[k]] = 0; q.push(pos[k]); while(!q.empty()){ int now = q.front(); q.pop(); for(int i=0; i<2; i++){ int tmp = next[now][i]; if(dis[tmp] < 0 && end[tmp] >= 0){ dis[tmp] = dis[now] + 1; q.push(tmp); } } } for(int i=0; i<cnt; i++) g[k][i] = dis[pos[i]]; } int solve(int n){ pos[0] = 0; cnt = 1; for(int i=0; i<L; i++) if(end[i] > 0) pos[cnt++] = i; for(int i=0; i<cnt; i++) bfs(i); for(int i=0; i<(1<<n); i++) for(int j=0; j<cnt; j++) dp[i][j] = INF; dp[0][0] = 0; for(int i=0; i<(1<<n); i++) for(int j=0; j<cnt; j++) if(dp[i][j] < INF){ for(int k=0; k<cnt; k++){ if(g[j][k] < 0) continue; if(j == k) continue; dp[i | end[pos[k]]][k] = min(dp[i | end[pos[k]]][k], dp[i][j] + g[j][k]); } } int ans = INF; for(int i=0; i<cnt; i++) ans = min(ans, dp[(1<<n)-1][i]); return ans; } }; char buf[1010]; Trie ac; int main(){ #ifdef sxk freopen("in.txt", "r", stdin); #endif // sxk int n, m; while(scanf("%d%d", &n, &m) == 2){ if(n == 0 && m == 0) break; ac.init(); for(int i=0; i<n; i++){ scanf("%s", buf); ac.insert(buf, 1<<i); } for(int i=0; i<m; i++){ scanf("%s", buf); ac.insert(buf, -1); } ac.build(); printf("%d\n", ac.solve(n)); } return 0; }
版权声明:本文为sxk原创文章,转载请附加本文链接^_^
时间: 2024-12-27 14:26:12