Main topic: give a string s, so that f (x) represents the maximum number of occurrences of all lengths of X in a substring of s. F (1). F (Length (S))
Build the SAM and then find right, and you can press the topological sequence DP. Right is the number of paths to the end state of a point, and the last chain on the parent tree is the end state ... Then use right to update the answer.
SPOJ Card constant: Started with Dfs on the bombing, instead of BFS on a .
(Stick to the puzzle: We construct the SAM of S, so for a node s, its length range is [Min (s), Max (s)], and his number of occurrences are | Right (s) |. Then we use | Right (s) | To update the value of F (Max (s)). At the same time finally, from large to small in turn f (i) to update f (i-1) can be. )
-----------------------------------------------------------------------------
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;Const int cn = +;const int MAXN = 1000009;bool VIS[MAXN];int RIGHT[MAXN], ANS[MAXN], deg[maxn], n = 0, n;Char S[MAXN]; struct Node {Node *CH[CN], *FA;int len, id;} POOL[MAXN], *pt, *root, *last;node* newNode (int v) {memset (pt->ch, 0, sizeof pt->ch);pt->fa = 0;Pt->len = v;pt->id = n++;return pt++;}void Sam_init () {pt = pool;root = last = NewNode (0);}void Extend (int c) {Node *p = last, *NP = NewNode (P->len + 1);For (; p &&!p->ch[c]; p = p->fa)P->ch[c] = NP;if (!p)np->fa = root;else {node* q = p->ch[c];if (p->len + 1 = = Q->len)NP->FA = q;else {node* NQ = NewNode (P->len + 1);memcpy (nq->ch, q->ch, sizeof q->ch);NQ->FA = q->fa;Q->fa = Np->fa = NQ;For (; p && p->ch[c] = = q; p = p->fa)P->ch[c] = NQ;}}Last = NP;}struct Edge {int to;edge* Next;} E[MAXN], *pt = E, *HEAD[MAXN];void Addedge (int u, int v) {deg[pt->to = v]++; Pt->next = Head[u]; Head[u] = pt++;}void Sam_build () {scanf ("%s", s);N = strlen (s);for (int i = 0; i < N; i++)Extend (S[i]-' a ');}queue<node*> Q;queue<int> Q;void Addedge () {memset (deg, 0, sizeof deg);memset (Vis, 0, sizeof vis);Q.push (root);Vis[root->id] = true;While (!q.empty ()) {node* t = Q.front (); Q.pop ();for (int i = 0; I < cn; i++) if (T->ch[i]) {Addedge (T->ch[i]->id, t->id);if (!vis[t->ch[i]->id]) {Q.push (T->ch[i]);Vis[t->ch[i]->id] = true;}}}}void GetRight () {memset (right, 0, sizeof right);For (node* t = last; t; t = T->FA)Right[t->id] = 1;Q.push (last->id);While (! Q.empty ()) {int x = Q.front (); Q.pop ();For (edge* e = head[x]; e; e = e->next) {Right[e->to] + = right[x];if (!--deg[e->to])Q.push (e->to);}}}void Update () {memset (Vis, 0, sizeof vis);Q.push (root);Vis[root->id] = true;While (!q.empty ()) {node* t = Q.front (); Q.pop ();Ans[t->len] = max (Ans[t->len], right[t->id]);for (int i = 0; I < cn; i++) if (T->ch[i] &&!vis[t->ch[i]->id]) {Q.push (T->ch[i]);Vis[t->ch[i]->id] = true;}}}void Solve () {getRight ();update ();for (int i = N; i.)Ans[i] = max (Ans[i], ans[i + 1]);for (int i = 1; I <= N; i++)printf ("%d\n", Ans[i]);}int main () {sam_init ();sam_build ();Addedge ();solve ();return 0;}
-----------------------------------------------------------------------------
SPOJ8222 substrings (suffix automaton + dp)