Problem Description
CA loves strings, especially the substrings.
Now CA has a string S which consists of N digits. However, she split this string into two non-empty strings. Specifically, CA spilt the string into S1 and S2 two substrings at the middle of ith character and (i+1)th. Now, she wonders that there are how many non-empty strings are substring of S1 or S2 for each i.Input
First line contains T denoting the number of testcases.
T testcases follow. Each testcase contains a integer in the first line, denoting N, the length of string S. The second line is a string whose length is N.
1≤T≤10, 2≤N≤200000Output
For each testcase, you need output 1 line.
Let Fj represent the answer when i=j in this testcase, you need to output ∑N−1j=1Fj×100013N−j−1 mod (109+7)Sample Input
2
2
00
4
0101Sample Output
1
13300539Hint
In the second case, when i=1 , S1 is “0”, S2 is “101”, All the Strings that satisfy the conditions are “0”,”1”,”10”,”01”,”101”.Source
BestCoder Round #78 (div.1)
这是bc的好题啊.. 而且还是NanoApe出的啊..
附上题解,挺详细的:
表示在做这道题的时候一言不合把全部变量都变成了long long..
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define LL long long
using namespace std;
const LL Maxn = 200010;
const LL Mod = 1e9+7;
LL F[Maxn*2], d[Maxn*2], ch[Maxn*2][10], tot, now, G[Maxn*2];
char s[Maxn]; LL len;
LL mx[Maxn*2], mi[Maxn*2];
LL Rsort[Maxn*2], rk[Maxn*2];
void clear ( LL x ){ mx[x] = 0; mi[x] = len+1; memset ( ch[x], 0, sizeof (ch[x]) ); G[x] = 0; }
LL copy ( LL p, LL c ){
LL x = ++tot, y = ch[p][c];
d[x] = d[p]+1; clear (x);
for ( LL i = 0; i < 10; i ++ ) ch[x][i] = ch[y][i];
F[x] = F[y]; F[y] = x;
while ( ~p && ch[p][c] == y ){ ch[p][c] = x; p = F[p]; }
return x;
}
void add ( LL c ){
LL p, o;
if ( p = ch[now][c] ){
if ( d[p] != d[now]+1 ) copy ( now, c );
now = ch[now][c];
}
else {
d[o=++tot] = d[now]+1; p = now; now = o; clear (o);
while ( ~p && !ch[p][c] ){ ch[p][c] = o; p = F[p]; }
F[o] = ~p ? ( d[p]+1 == d[ch[p][c]] ? ch[p][c] : copy ( p, c ) ) : 0;
}
}
LL _max ( LL x, LL y ){ return x > y ? x : y; }
LL _min ( LL x, LL y ){ return x < y ? x : y; }
LL f[Maxn], g[Maxn], ans;
LL cf[Maxn];
int main (){
LL i, j, k, T;
scanf ( "%I64d", &T );
cf[0] = 1;
for ( i = 1; i <= 200000; i ++ ) cf[i] = ((LL)cf[i-1]*100013)%Mod;
while ( T -- ){
scanf ( "%I64d", &len );
scanf ( "%s", s+1 );
F[0] = -1; tot = now = 0; clear (0);
for ( i = 1; i <= len; i ++ ){ add (s[i]-'0'); mx[now] = mi[now] = i; }
memset ( Rsort, 0, sizeof (Rsort) );
for ( i = 1; i <= tot; i ++ ){ Rsort[d[i]] ++; G[i] = 1; }
for ( i = 1; i <= len; i ++ ) Rsort[i] += Rsort[i-1];
for ( i = tot; i >= 1; i -- ) rk[Rsort[d[i]]--] = i;
for ( i = tot; i >= 1; i -- ){
mx[F[rk[i]]] = _max ( mx[rk[i]], mx[F[rk[i]]] );
mi[F[rk[i]]] = _min ( mi[rk[i]], mi[F[rk[i]]] );
for ( j = 0; j < 10; j ++ ){
if ( ch[rk[i]][j] ) G[rk[i]] += G[ch[rk[i]][j]];
}
}
for ( i = 0; i < 10; i ++ ){
if ( ch[0][i] ) G[0] += G[ch[0][i]];
}
ans = G[0];
memset ( f, 0, sizeof (f) );
memset ( g, 0, sizeof (g) );
for ( i = 1; i <= tot; i ++ ){
LL l = d[F[i]]+1, r = d[i];
l = _max ( l, mx[i]-mi[i]+1 );
if ( l > r ) continue;
g[mx[i]-r+1] ++;
g[mx[i]-l+2] --;
f[mi[i]] -= (r-l+1);
}
k = 0;
for ( i = 1; i <= len; i ++ ){
k = (k+g[i])%Mod;
f[i] = (f[i]+k)%Mod;
}
for ( i = 1; i <= len; i ++ ) f[i] = (f[i]+f[i-1])%Mod;
for ( i = 1; i < len; i ++ ) f[i] = ((ans-f[i])%Mod+Mod)%Mod;
LL ssum = 0;
for ( i = 1; i < len; i ++ ) ssum = (ssum+((LL)f[i]*cf[len-i-1])%Mod) % Mod;
printf ( "%I64d\n", (ssum+Mod)%Mod );
}
return 0;
}