problem:
Give you n a string, n (1 <= n <= 2 * 104), all worn lengths plus no more than 3 * 105. Each string has a value. This value [-1000, 1000].
Ask not to disturb the string order, take several strings from it, so that the previous string is the substring of the latter string, to satisfy the preceding conditions of the string is worth and maximum, to find this value.
Think:
Establish an AC automaton. The following check takes the maximum value with each string being the last string to fetch. Then, when checking the I-string, it is the value of the zero-node of the string, all the fail pointers to the root node and the top of his node, plus the values of the I-string. The direct violence, it is n*m, must be timed out.
Because each node has been fail will point to the root node, so convert him into a fail tree. We find that when a node in the fail tree is changed, it affects his descendants, so you can use time stamps to turn the fail tree into linear so that it can be optimized with a segment tree.
But besides fail, the parent node in the Trie tree is also affected by a node. So we sweep through all the characters and save the last node that we went to is the parent of his trie tree. Compare it to the line tree of the fail tree.
This problem built three trees, trie tree, fail tree, line segment tree. Vetor to save the memory of the tree, all long long is changed to int only from the MLE into AC.
Code: [CPP] View plain copy print? const int kind = 26; const int nn = 333333; int cnt;//ac status char str[nn];//all characters together int pos[nn]; int fail[nn];//fail pointer for each state Int child[nn][kind];//trie tree int ans;//Final Answer int val[nn];//each word input value int tal;// Timestamp state number Vector<int>v[nn];//fail tree int in[nn];//timestamp int out[nn]; int mx[nn<<2];//segment Tree inline int newnode () { ++cnt; for (int i=0; i<kind; ++i) child[cnt][i] = -1; return cnt; } Void insert (char *str, int root, inT id) { int p = root; int len = strlen (str); for (int i=0; i < len; ++i) { int k = str[i] - ' A '; if (child[p][k] == -1) child[p][k] = newnode (); p = child[p][k]; } } void Build_fail (int root) { queue<int>q; int p = root; q.push (p); while (!q.empty ()) { p = q.front (); q.pop (); if (P) v[fail[p]].push_back (p); for (