HDU3247 AC自动机+dp
题意:给出n个资源,m个病毒,将资源串拼接成一个串,必须包含所有的资源串,可以重叠,但是不能包含病毒,问最小的长度为多少
题解:所有串建AC自动机。对以资源串结尾的结点跑bfs,求出到其他资源串结尾的最小距离。当前结点的fail结点不能入队列,因为当前结点读下一个字符可能会遇到禁止字符串,而fail结点读相同字符可能没有遇到禁止字符串...所以每次直接将nex的可行结点入队列。(fail结点不入队列,直接设为与当前结点距离为0应该也是可行的,然而WA了)很多时候我都开始质疑数据问题了...
如果当前字符串本身包含另一个资源串,那距离不应当是0吗?有一种解释是dp的时候经过 | 操作就可以了。
1 #include <bits/stdc++.h> 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 #define ll long long 6 #define lson l, m, rt<<1 7 #define rson m+1, r, rt<<1|1 8 #define st first 9 #define nd second 10 #define mp make_pair 11 #define pii pair<int, int> 12 #define gg puts("gg"); 13 #define local 14 //#define out1 15 using namespace std; 16 const int N = 6e4+10; 17 const int inf = 0x3f3f3f3f; 18 int id(char c){ 19 return c == '1'; 20 } 21 struct Tire{ 22 int nex[N][2], fail[N],end[N]; 23 int root, L; 24 int node[15], tot; 25 int newnode(){ 26 nex[L][0] = nex[L][1] = -1; 27 end[L] = 0; 28 return L++; 29 } 30 void init(){ 31 L = tot = 0; 32 root = newnode(); 33 } 34 void insert(char* s, int tag){ 35 int now = root; 36 for(int i = 0; s[i]; i++){ 37 int p = id(s[i]); 38 if(nex[now][p] == -1) 39 nex[now][p] = newnode(); 40 now = nex[now][p]; 41 } 42 if(tag >= 0) 43 end[now] |= 1<<tag; 44 else end[now] = -1; 45 } 46 void build(){ 47 queue<int> Q; 48 fail[root] = root; 49 for(int i = 0; i < 2; i++){ 50 int& u = nex[root][i]; 51 if(u == -1) 52 u = root; 53 else{ 54 fail[u] = root; 55 Q.push(u); 56 } 57 } 58 while(!Q.empty()){ 59 int now = Q.front(); 60 Q.pop(); 61 for(int i = 0; i < 2; i++){ 62 int& u = nex[now][i]; 63 if(u == -1) 64 u = nex[ fail[now] ][i]; 65 else{ 66 fail[u] = nex[ fail[now] ][i]; 67 end[u] |= end[ fail[u] ]; 68 Q.push(u); 69 } 70 } 71 } 72 } 73 }; 74 Tire ac; 75 char s[N]; 76 void gmin(int& a, int b){ 77 if(a > b) a = b; 78 } 79 int dis[N], ve[N], tot; 80 int w[555][555]; 81 82 void bfs(int node, int i){ 83 memset(dis, 0x3f, sizeof(dis)); 84 queue<int> Q; 85 Q.push(node); dis[node] = 0; 86 int s = 0; 87 88 #ifdef out1 89 int j = node; 90 while(ac.fail[j] != ac.root){ 91 j = ac.fail[j]; 92 dis[j] = 0; 93 } 94 dis[j] = 0; 95 #endif 96 97 while(!Q.empty()){ 98 int sz = Q.size(); 99 s++; 100 while(sz--){ 101 int f = Q.front(); Q.pop(); 102 for(int j = 0; j < 2; j++){ 103 int to = ac.nex[f][j]; 104 if(dis[to] < inf||ac.end[to] < 0) continue ; 105 Q.push(to); 106 dis[to] = s; 107 108 #ifdef out1 109 while(ac.fail[to] != ac.root&&dis[ac.fail[to]] == inf){ 110 to = ac.fail[to]; 111 dis[to] = s; 112 } 113 #endif 114 } 115 } 116 } 117 for(int j = 0; j < tot; j++) 118 w[i][j] = dis[ ve[j] ]; 119 } 120 int dp[555][1<<11]; 121 int main(){ 122 #ifdef locl 123 freopen("in", "r", stdin); 124 #ifdef out1 125 freopen("out1", "w", stdout); 126 #else 127 freopen("out2", "w", stdout); 128 #endif // out1 129 #endif // locl 130 int n, m, t, ca = 1; 131 while(~scanf("%d%d", &n, &m), n+m){ 132 ac.init(); 133 134 memset(w, 0x3f, sizeof(w)); 135 for(int i = 0; i < n; i++){ 136 w[i][i] = 0; 137 scanf("%s", s); 138 ac.insert(s, i); 139 } 140 for(int i = 0; i < m; i++){ 141 scanf("%s", s); 142 ac.insert(s, -1); 143 } 144 ac.build(); 145 146 tot = 0; 147 for(int i = 0; i < ac.L; i++) 148 if(!i||ac.end[i] > 0) ve[tot++] = i; 149 memset(w, 0x3f, sizeof(w)); 150 for(int i = 0; i < tot; i++) 151 bfs(ve[i], i); 152 // for(int i = 0; i < tot; i++){ 153 // for(int j = 0; j < tot; j++) 154 // printf("%10d ", w[i][j]); 155 // puts(""); 156 // } 157 158 memset(dp, 0x3f, sizeof(dp)); 159 for(int i = 0; i < tot; i++) 160 dp[i][ ac.end[ve[i]] ] = w[0][i]; 161 for(int i = 0; i < (1<<n); i++){ 162 for(int j = 0; j < tot; j++){ 163 if( dp[j][i] < 0x3f3f3f3f ) for(int k = 0; k < tot; k++) 164 if(j != k&&w[j][k] < 0x3f3f3f3f) 165 gmin(dp[k][i|ac.end[ve[k]]], dp[j][i]+w[j][k]); 166 } 167 } 168 169 // for(int i = 0; i < n; i++) 170 // for(int j = 0; j < (1<<n); j++) 171 // printf("%d %d: %d\n", i, j, dp[i][j]); 172 173 int ans = inf; 174 for(int i = 0; i < tot; i++) 175 ans = min(ans, dp[i][ (1<<n)-1 ]); 176 printf("%d\n", ans); 177 } 178 return 0; 179 } 180 /* 181 2 2 182 1110 183 0111 184 101 185 1001 186 187 3 3 188 0001000 189 00100 190 010 191 11 192 111 193 1111 194 */
诸神对凡人心生艳羡,厌倦天堂。