Surface
Portal
Ideas
First of all, the best part of the problem is that the explanation it gives us about $next$ is fantastic ... I can even say that my kmp is not reborn until after this problem.
Then the text:
How do I find an array of $num$?
The input of this problem is 1e6 characters, obviously need $o\left (N\right) $ about the level of the algorithm to solve
First see the definition of $num$: The number of common prefixes that do not overlap each other
What does that mean?
Description $num$ is different from the $next$ record is a maximum value, it records a and value
And this and the value, can be pushed out.
Consider a prefix $i$ of $next[i]$, which looks like this:
Among them, $next [i]$, $next [next[i]]$, $next [next[next[i]]]$ ...] is the common prefix of the string I, and only they are public
So, in fact, as long as we are in the process of seeking $next$, by the way, the public prefix of the number of recursion, we get a weakened version of the $num$ array: can overlap the number of public prefix, we call it $ans$
How to remove overlapping?
Or look at the picture above?
First the $next$ array has a property: $next [i] < i$
That is, once you have a recursive n-layer next, which is smaller than half the length of the original prefix I, then this next hand-launched answer $ans$ is the $num$ of I.
A problem
If we get the string is 1e6 ' a ', then the above algorithm will be stuck into $o\left (n^2\right) $, we can think of the truth (every time recursion will only put Next[i] smaller 1)
Then we need to do an optimization to solve this problem, and the core of the problem is: reduce recurrence recursion
Reduce repetitive recursion ... Did you think of anything?
Yes, it is the same way as when you ask for $next$!
We will recursively use the variable $j$ value is not updated, so that after the answer of $i$, $j $ position must be on the left of $\frac i2$, that is, it has met the requirements of
Then the recursive solution, the total time efficiency is $o\left (n\right) $
Code
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define LL Long Longusing namespaceStdConstll mod=1e9+7;intn,fail[1000010],ans[1000010];ll CNT;Chara[1000010];intMain () {intT,I,J;SCANF ("%d", &t); while(t--) {scanf ("%s", a); N=strlen (a); memset (fail,0,sizeof(fail)); j=0; ans[0]=0; ans[1]=1; for(i=1; i<n;i++) {//Solve next while(j&& (A[i]!=a[j])) j=fail[j]; j+= (A[i]==a[j]); fail[i+1]=j;ans[i+1]=ANS[J]+1;//recursive record ans} j=0; cnt=1; for(i=1; i<n;i++) {//Solve num while(j&& (A[i]!=a[j])) j=fail[j]; j+= (A[i]==a[j]); while((j<<1) > (i+1)) J=fail[j]; Cnt= (cnt* (LL) (Ans[j]+1))%mod;//Remember +1} printf ("%lld\n", CNT); }}
[NOI2014] [bzoj3670] Zoo [kmp+next Array application]