Test instructions: For each location, how many identical strings are counted.
Analysis: According to the meaning of the title, the Fail tree will be found, for the first character: ans[i] = ans[i-1] + (ans[i-1]-ans[i-1]) + cal (i);
Cal (i) is the and of the longest public suffix that calculates s[1...i-1] all substrings and s[1...i]. In other words, depending on the character of the suffix automaton, you can know the length and number of public suffixes (the size of the right collection) for all locations of the suffix s[1...i], along the parent tree. It is easy to calculate cal (i), as long as a new character is added each time, on the parent tree to go to the root, while walking statistics val[i]* (Right[pre[i]]-right[i]). Because blogger I was building suffix automata while calculating ans, so the parent tree is dynamic, so the blogger used LCT to maintain.
Spit Groove: Look at the angle of the problem can have a lot of, obviously the following code can reflect my view of the problem is obviously not very good. For this problem, hard to learn LCT, but later read others blog found can be directly with the tree chain to write.
/************************************************author:D arktongcreated TIME:2016/9/6 22:58:31File name:5 1nod_simplekmp.cpp*************************************************/#include<bits/stdc++.h>using namespacestd;typedef unsignedLong LongUll;typedefLong LongLL;Const intINF =0x3f3f3f3f;Const DoubleEPS = 1e-9;Const intMOD = 1e9+7;Const intMAXN =2*100000+ -; LL ANS[MAXN];structsplay_tree{intch[maxn][2], PRE[MAXN], DPRE[MAXN]; //Dpre for tree-tree connections//pre for in-tree connections intLAZY[MAXN], MVAL[MAXN], MR[MAXN]; LL SUM[MAXN]; intgo[maxn][ -], RIGHT[MAXN], VAL[MAXN]; intsz, last, root; voidPushdown (intx) { intL = ch[x][0], R = ch[x][1]; if(l) lazy[l] + = Lazy[x], right[l] + lazy[x], mr[l] + =Lazy[x]; if(r) lazy[r] + = Lazy[x], Right[r] + lazy[x], mr[r] + =Lazy[x]; LAZY[X]=0; MR[X]=Max (Right[x], Max (Mr[l], mr[r])); } voidPushup (intx) {Sum[x]= (sum[ch[x][0]] + sum[ch[x][1]] + val[x]*mval[x])%MOD; MR[X]= Max (right[x], Max (mr[ch[x][0]], mr[ch[x][1]])); //Ch[x][1] is not the son of X, because x is not the root. } //rotation operation (OK), note: For the element being rotated, its dpre=0, that is, to the auxiliary tree in operation, does not affect the original tree. voidRotateintx) { inty = pre[x], d = (ch[y][1]==x); CH[Y][D]= ch[x][!d]; pre[ch[x][!D]] =y; PRE[X]= Pre[y]; Pre[y] =x; ch[x][!D] =y; if(Dpre[y]) dpre[y]=0, dpre[x]=1; Elsech[pre[x]][ch[pre[x]][1]==y] =x; Pushup (y);//pushup (x); } //Direct access to Node O and select it to the root voidPintx) { if(!dpre[x]) P (Pre[x]);//find the root of the heavy chain, and then pass the sign down again.pushdown (x); } voidSplay (intx) {P (x); while(!Dpre[x]) { intf = pre[x], FF =Pre[f]; if(Dpre[f]) rotate (x); Else if((ch[ff][1]==f) = = (ch[f][1]==x)) rotate (f), rotate (x); Elserotate (x), rotate (x); } pushup (x); } //auxiliarytree link operation (data update) voidAccess (intx) { inty =0; for(; X;y=x, x=Pre[x]) {splay (x); //in order to get rid of the weight of the son, the son rotated upon its left subtreedpre[ch[x][1]] =1;//Get rid of the yuan, son .ch[x][1] =y; Dpre[y]=0;//add a new heavy son vMVAL[X] = right[x]-mr[ch[x][1]]; Pushup (x); } } //add edge, connect two tree,u->v; voidLinkintUintv) {Access (U); Pre[u]=v; Dpre[u]=1; Access (U); } voidCutintx) {Access (x); splay (x); intL = ch[x][0]; PRE[L]=0; DPRE[L] =1; ch[x][0] =0; Access (x); } intFaintu) {Access (U); Splay (U); U= ch[u][0]; while(ch[u][1]) U = ch[u][1]; returnu; } voidSAM () { last= root = Sz =1; } voidIniintSzintv) {Val[sz]= V;mval[sz] =0; ch[sz][0]=ch[sz][1]=0; DPRE[SZ]=1; PRE[SZ]=sum[sz]=lazy[sz]=right[sz]=0; MR[SZ]=0; memset (Go[sz],0,sizeofGo[sz]); } voidExtendintWintth) { intp =Last ; intNP = ++sz; INI (SZ, val[p]+1);//leaf node while(P && go[p][w] = =0) Go[p][w] = NP, p =FA (P); if(p = =0) Link (NP, root); Else{ intQ =Go[p][w]; if(Val[p] +1==Val[q]) Link (NP, q); Else{ intNQ = ++sz; INI (SZ, val[p]+1);//Non-leaf nodememcpy (Go[nq], go[q],sizeofGo[q]); MR[NQ]= Right[nq] = Right[q]; MVAL[NQ] =Right[q]; intFAQ =FA (q); Cut (q); Link (q, NQ); Link (NP, NQ); Link (NQ, FAQ); while(P && go[p][w] = = q) go[p][w] = NQ, p =FA (P); }} last=NP; Ans[th]=Cal (NP); } LL Cal (intx) {x=fa (x); Access (x); Splay (x); //Updatelazy[x]++; RIGHT[X]++; MVAL[X]=Right[x]; Pushup (x); returnSum[x]; }}SLT;CharS[MAXN];intMain () {//freopen ("OUT.txt", "R", stdin);//freopen ("Xx1.txt", "w", stdout); intT, cas=1, N; scanf ("%d%s", &N, s); Slt. SAM (); Slt.ini (1,0); for(intI=0; i<n;++i) {slt.extend (S[i]-'a', i); }//for (int i=0;i<n;++i) cout<<ans[i]<< ""; cout<<endl; for(intI=2; i<n;++i) Ans[i] = (2*ans[i-1]-ans[i-2]+ANS[I]+MOD)%MOD; for(intI=0; i<n;++i) printf ("%lld\n", Ans[i]); return 0;}