Question:
Give N source strings and M virus strings
The word with the most length contains all the source strings and does not contain any virus strings.
All strings are 01
Ideas:
Only 10 Source strings
In the first step, we thought about creating a trie graph and then directly setting up the spfa graph.
The result shows that DIS [60005] [1030] is out of memory.
At this time, we need to think
In fact, we only need to use nodes whose mark value is greater than 0.
Is the nodes that contain the pressure values.
Then we will first record what these nodes are
Then we found that less than 100 nodes
Therefore, run the spfa command 100 times to find the shortest path between the two
Then use this distance to decompress DP.
The array becomes DP [1030] [100 ].
Code:
# Include "cstdlib" # include "cstdio" # include "cstring" # include "cmath" # include "queue" # include "algorithm" # include "map" # define INF 0x7fffffff # include "iostream" using namespace STD; int triecont; char BD [60021]; struct trie {int mark; // if Mark =-1 indicates that the value cannot be greater than 0, it indicates that the word int ID can be obtained; trie * Next [3], * fail; trie () {mark = id = 0; memset (next, 0, sizeof (next); fail = NULL ;}}; trie * root, * node [60002]; void Init (char * V, int K, int I D) {trie * P = root; For (INT I = 0; V [I]; I ++) {int TEP = V [I]-'0 '; if (p-> next [TEP] = NULL) {P-> next [TEP] = new trie (); node [triecont] = p-> next [TEP]; p-> next [TEP]-> id = triecont ++;} p = p-> next [TEP];} If (k = 0) p-> MARK = (1 <ID); else p-> MARK =-1;} void getac () {queue <trie *> q; q. push (Root); While (! Q. empty () {trie * P = Q. front (); q. pop (); For (INT I = 0; I <2; I ++) {If (p-> next [I] = NULL) {If (P = root) P-> next [I] = root; else p-> next [I] = p-> fail-> next [I];} else {If (P = root) P-> next [I]-> fail = root; else p-> next [I]-> fail = p-> fail-> next [I]; q. push (p-> next [I]); If (P! = Root) {If (p-> next [I]-> MARK =-1 | p-> next [I]-> fail-> MARK =-1) p-> next [I]-> MARK =-1; else p-> next [I]-> MARK | = p-> next [I]-> fail-> MARK ;}}} struct node {int ID ;}; int dis [60001], use [60001]; int useful [222], Juli [222] [222]; void spfa (int u, int N, int S, int CNT) {queue <node> q; int I; for (I = 0; I <= N; I ++) {dis [I] = inf; use [I] = 0;} dis [u] = 0; use [u] = 1; node now; now. id = u; q. push (now); While (! Q. empty () {node cur = Q. front (); q. pop (); for (I = 0; I <2; I ++) {int v = node [cur. id]-> next [I]-> ID; If (node [v]-> MARK =-1) continue; If (DIS [v]> dis [cur. id] + 1) {dis [v] = dis [cur. id] + 1; now. id = V; If (! Use [now. id]) {use [now. id] = 1; q. push (now) ;}}}for (INT I = 0; I <CNT; I ++) juli [s] [I] = dis [useful [I];} int DP [1300] [222]; int main () {int n, m; while (scanf ("% d", & N, & M), (N + M) {triecont = 0; root = new trie (); node [triecont] = root; root-> id = triecont ++; For (INT I = 0; I <n; I ++) {char X [1004]; scanf ("% s", x); Init (x, 0, I) ;}while (M --) {scanf ("% s", BD); Init (BD, 1, 1);} getac (); int CNT = 0; useful [CNT ++] = 0; For (INT I = 1; I <triecont; I ++) // find all the nodes we need {If (node [I]-> MARK> 0) Useful [CNT ++] = I ;}for (INT I = 0; I <CNT; I ++) // run each spfa {spfa (useful [I], triecont, I, CNT);} For (INT I = 0; I <CNT; I ++) for (Int J = 0; j <(1 <n); j ++) DP [J] [I] = inf; DP [0] [0] = 0; For (INT I = 0; I <(1 <n); I ++) // pressure DP {for (Int J = 0; j <CNT; j ++) {If (DP [I] [J] = inf) continue; for (int K = 0; k <CNT; k ++) {int TEP = node [useful [k]-> MARK | I; If (j = K) continue; If (Juli [J] [k] = inf) continue; DP [TEP] [k] = min (DP [TEP] [K], DP [I] [J] + Juli [J] [k]) ;}} int ans = inf; For (INT I = 0; I <CNT; I ++) ans = min (ANS, DP [(1 <n)-1] [I]); printf ("% d \ n", ANS);} return 0 ;}
[AC automatic machine + spfa + pressure DP] HDU 3247 resource archiver