MZL ' s Circle Zhou
Test instructions: Given two lengths not exceeding A/b (1 <= |a|,|b| <= 90000), X is a continuous substring of a, B is a continuous substring of y (x and Y can be empty strings); Q x+y The number of different strings formed?
Myth: Start mindedly to find out the total number of strings that can be formed, and subtract the same sub-string overlap Part of a, b; the SAM that you want to get through the continuous insertion of a+b does not get information; because X, y is an arbitrary substring, successive insertions result in a suffix that must be a and a prefix of b
Positive solution: Directly in the calculation of different substrings, do not calculate the repetition of <=> for a possible x suffix and the y prefix of the same and repeated calculations, all add x and y into the part of the minus prefix ;
That is to find the last character of the x CH, so that after the X can be added to the string does not start with ch , so that the repetition of the situation is avoided; (thought very well!!! )
The understanding of Sam:
After the SAM inserts a string, STEP[NP]-STEP[PRE[NP]] indicates the number of different substrings with the same point as the suffix of the state NP than the parent node PRE[NP];
After the SAM has been topologically:
<1> if the number of occurrences of the parent node can be obtained from the child node by iterating through the valid nodes first , the number of times each state occurs is 1, and then the number of different substrings is obtained by using step to solve a class of problems related to the number of occurrences; such as Hdu 4641 K-string
<2> If the initialization root is 1, the number of times each node is introduced cnt[g[p][v]] + = Cnt[p] will get all the substrings (of course different) from the initial state to the current state;
The point: Need for a string composition of the Sam's every State (node) to find g[u][j] = = 0 (that is, the above x can not have J this state transfer edge), if y start with J of the number of different substrings of the known, it is possible to contribute directly to the results Cnt[u] * C[j] Value (cnt[ U] denotes the number of strings of a string with the X state as the suffix of different substrings, C[j] indicates the number of substrings beginning with J in Y)
CNT set according to the properties of the above 2 can be directly recursive to get, that C set it?
In fact, after finding a cnt[u], if you have a J transfer Edge J, then the value of c[j] increases Cnt[u]?
There is one more problem: Sam can only find a point suffix, how to get started from each point?
Then insert the b in reverse order. (Good idea) This suffix becomes the prefix inside the suffix.
The various cases of B have been calculated, but because there can be empty strings, A's different substrings need to be added;
Pit: This problem data is very large, suspect is the result of% unsigned long long, using long long direct WA
Note: If the C collection is written inside the SAM, the C collection of the SA that is operated when the SA is called: Not SB.
1#include <iostream>2#include <cstdio>3#include <cstring>4 using namespacestd;5typedef unsignedLong Longll;6 7 Const intMAXN =100007;8 Const intSigma_size = -;9 Ten structsam{ One intSZ, last, pos[maxn<<1]; A intg[maxn<<1][sigma_size], pre[maxn<<1], step[maxn<<1]; -ll cnt[maxn<<1]; - the voidinit () { -SZ =0; last =1; -NewNode (0); - } + - voidNewNode (ints) { +PRE[++SZ] =0; ASTEP[SZ] =s; atmemset (G[sz],0,sizeof(G[sz])); - } - - intIdxCharCH) {returnCH-'a'; } - - voidInsert (Charch); in voidToposort (); - voidPresolve (ll*C); toll solve (ll*C); + - }sa, SB; the * voidSam::insert (Charch) { $NewNode (Step[last] +1);Panax Notoginseng intv = IDX (ch), NP = SZ, p =Last ; - while(P &&!)G[p][v]) { theG[P][V] =NP; +p =Pre[p]; A } the + if(p) { - intQ =G[p][v]; $ if(Step[q] = = Step[p] +1) $PRE[NP] =Q; - Else{ -NewNode (Step[p] +1); the intNQ =sz; - for(inti =0; I < sigma_size;i++)WuyiG[nq][i] =G[q][i]; the -PRE[NQ] =Pre[q]; WuPRE[Q] = PRE[NP] =NQ; - About while(P && g[p][v] = =q) $G[P][V] = NQ, p =Pre[p]; - } - } - ElsePRE[NP] =1; ALast =NP; + } the - voidSam::toposort () { $ for(inti =0; I <= sz; i++) Cnt[i] =0; the for(inti =1; I <= sz; i++) cnt[step[i]]++; the for(inti =1; I <= sz; i++) Cnt[i] + = cnt[i-1]; the for(inti =1; I <= sz; i++) pos[cnt[step[i]]--] =i; the } - in voidSAM::p Resolve (ll*C) { the Toposort (); the for(inti =0; I <= sz; i++) Cnt[i] =0; Aboutcnt[1] =1; the the for(inti =1; I <= sz; i++{//the number of times each node has been recursively pushed from Root to the intU =Pos[i]; + for(intj =0; J < Sigma_size; J + +){ - intv =G[u][j]; the if(v = =0)Continue;BayiC[J] + =Cnt[u]; theCNT[V] + =Cnt[u]; the } - } - } the thell Sam::solve (LL *C) { the Toposort (); the for(inti =0; I <= sz; i++) Cnt[i] =0; -cnt[1] =1; the theLL ret =0; the for(inti =1; I <= sz; i++){94 intU =Pos[i]; the for(intj =0; J < Sigma_size; J + +){ the intv =G[u][j]; the if(v = =0) ret + = cnt[u] *C[j];98 ElseCNT[V] + =Cnt[u]; About } -RET + =Cnt[u]; x + ""101 }102 returnret;103 }104 the CharSTR[MAXN];106 intMain ()107 {108 intT;109scanf"%d",&T); the while(t--){111scanf"%s", str); the intn =strlen (str);113 sa.init (); the for(inti =0; i < n; i++) the SA. Insert (Str[i]); the 117scanf"%s", str);118n =strlen (str);119 sb.init (); - for(inti = n-1; I >=0; i--)//* *121 SB. Insert (Str[i]);122 123 ll C[sigma_size];124memset (C,0,sizeof(C)); the sb.presolve (C);126 127printf"%llu\n", Sa.solve (C)); - }129}
Hdu 5343 MZL ' s Circle Zhou SAM