Poj 3415 SAM suffix Automatic Machine
Question:
Give two strings and ask all the substrings of the two strings (if the positions are different, the two substrings are repeated ), the number of public substrings with a length greater than or equal to k.
Set string A to construct SAM and string B to match string
State: sum, which indicates the number of times this state appears. That is to say, the number of substrings in string B can enter this state.
The parent node is updated in reverse Topology Sorting.
Matching Process:
Note that the length of the string entering a certain state is not fixed during the matching process.
When the length of each matching lcs is greater than or equal to n, the number of sub-strings in the current status is: (lcs-max (n, p-> f-> len + 1) + 1 ), this quantity is not fixed. The number of occurrences in this status is p-> right.
If p-> f-> len> = n, the parent State has a matched substring, and the number of matched substrings is fixed.
First, the number of unfixed substrings is processed in the matching process. Ans + = (lcs-max (n, p-> f-> len + 1) + 1) * p-> right; at this time, the number of times that the father's status appears increases by one, p-> f-> sum ++;
For the father status, because the number of child strings that match the status is fixed, you can first obtain the number of times that the status appears, and wait until the matching is complete before processing.
Number of times the parent node is updated in reverse Topology Sorting
For the status of each node> = n
Ans + = sam. pool [I]. sum * sam. pool [I]. right * (sam. pool [I]. len-max (n, sam. pool [I]. f-> len + 1) + 1 );
// Number of occurrences * right set size * Number of matching substrings
// Len indicates the longest acceptable String Length in this state, that is, max, // The shortest String Length acceptable for this state is p-> f-> len + 1 // The substring is stored in the state when and only when the string S, ST (S )! = NULL, S is the substring. // The number of different substrings that each State in SAM can represent is the val-the val of the parent node, or each time you create a parent-child relationship, the number of substrings generated by this state is accumulated // The number of substrings that appear equals to the set size of the right in the state, not yet # include
# Include
# Include
# Include
# Include
Using namespace std; const int maxn = 100100; struct suffixautomaton {struct node {long len; // maximum length allowed to this State, that is, max (s) long right; // This status has several locations in this string, that is, the size of the right set long sum; node * f, * ch [60]; // node () {} node (int l) {len = l; f = NULL; right = 0; sum = 0; memset (ch, 0, sizeof (ch ));} int calc () // returns the number of substrings in this status {if (f = NULL) return 0; // return len-(f-> len );}}; node * root, * last; node pool [maxn * 2]; // Int cnt; // number of nodes int tot; // number of different substrings that the current sam can represent. When a child-parent node is created, calculate how many substrings can be expressed at a time. // when changing the child-parent relationship, you must first subtract the number of substrings represented by the previous state void init () {root = last = pool; memset (root, 0, sizeof (node); cnt = 1; tot = 0;} node * new_node (int l = 0) {node * x = pool + cnt ++; memset (x, 0, sizeof (node); if (l! = 0) x-> len = l; return x;} void add (char ch) {int c = ch-'A'; node * p = last, * np = new_node (last-> len + 1); while (p &&! P-> ch [c]) p-> ch [c] = np, p = p-> f; if (NULL = p) {np-> f = root; // create a sub-parent tot + = np-> calc (); // calculate the added sub-string. The same below} else {if (p-> ch [c]-> len = p-> len + 1) {np-> f = p-> ch [c]; tot + = np-> calc ();} else {node * q = p-> ch [c], * nq = new_node (); * nq = * q; // nq also establishes a child parent relationship. nq-> f = q-> f; nq-> len = p-> len + 1; // create nq tot-= q-> calc (); // Replace the sub-parent relationship with the q-> f = np-> f = nq; tot + = q-> calc () + nq-> calc () + np-> calc (); // here, we create three new child parent relationships while (p & p-> ch [c] = q) p-> ch [c] = nq, p = p-> f;} last = np;} int bus [maxn * 2]; // process int sorted [maxn * 2]; // 0 -- (cnt-1) void findr (char str []) // process the size of the right set in a certain state. If you want to locate the position, node must have something to mark position {int l = strlen (str); memset (bus, 0, sizeof (bus); for (int I = 0; I
Ch [str [I]-'a'])-> right ++; for (int I = cnt-1; I> 0; I --) if (pool [sorted [I]. f) pool [sorted [I]. f-> right + = pool [sorted [I]. right; root-> right = 0; // restore} void solve () // sum {node * p = root; for (int I = cnt-1; I> 0; I --) if (pool [sorted [I]. f) pool [sorted [I]. f-> sum + = pool [sorted [I]. sum; root-> sum = 0 ;}}; suffixautomaton sam; char str [maxn]; char str2 [maxn]; int main () {long n; while (scanf ("% lld", & n), n) {scanf ("% s", str); sam. init (); int len = strlen (str); for (int I = 0; I
Ch [c]) p = p-> ch [c], lcs ++; else {while (p &&! P-> ch [c]) p = p-> f; if (p = NULL) p = sam. root, lcs = 0; else lcs = p-> len + 1, p = p-> ch [c];} if (lcs> = n) {ans + = (lcs-max (n, p-> f-> len + 1) + 1) * p-> right; // It is not fixed. Directly processed p-> f-> sum ++; // The number of occurrences of the father plus one} sam. solve (); for (int I = 0; I
= N) // For the conforming vertex, ans + = sam. pool [I]. sum * sam. pool [I]. right * (sam. pool [I]. len-max (n, sam. pool [I]. f-> len + 1) + 1);} printf ("% lld \ n", ans);} return 0 ;}