Problem Description
Now, are Back,and have a task to do:
Given you a string s consist of lower-case 中文版 letters Only,denote F (s) as the number of distinct sub-string of S.
And you have some Query,each time for you should calculate F (S[L...R]), S[L...R] means the sub-string of ' s start from L-end at R.
Input
The contains integer T (1<=t<=5), denote the number of the test cases.
For each test cases,the the contains a string s (1 <= length of S <= 2000).
Denote the length of s by N.
The second line contains a integer q (1 <= q <= 10000), denote the number of queries.
Then Q lines Follows,each lines contains two integer l, r (1 <= l <= r <= N), denote a query.
Output
For each test cases,for each query,print the answer in one line.
Sample Input
2
Bbaba
5
3 4 2 2 2 5 2 4 1 4
baaba
5
3 3 3 4 1 4 3 5-5 5
Sample Output
3
1
7
5
8
1 3 8 5 1
the
The number of substrings with different intervals is obtained.
train of Thought
template topics, there are several solutions: string hash, suffix array, suffix automata ...
AC Code String Hash
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <cmath> #include <
Algorithm> #include <iostream> using namespace std;
const int HASH = 10007;
const int MAXN = 2100;
struct HashMap {int head[hash],next[maxn],size;
unsigned long long STATE[MAXN];
int F[MAXN];
void Init () {size=0;
Memset (head) (head,-1,sizeof);
int insert (unsigned long long val,int _id) {int h=val%hash;
for (int i=head[h]; I!=-1 I=next[i]) {if (val==state[i)) {int temp=f[i];
f[i]=_id;
return temp;
}} f[size]=_id;
State[size]=val;
NEXT[SIZE]=HEAD[H];
head[h]=size++;
return 0;
}} H;
const int seed = 13331;
unsigned long long P[MAXN];
unsigned long long S[MAXN];
Char STR[MAXN];
int ANS[MAXN][MAXN];
int main () {p[0]=1;
for (int i=1; i<maxn; i++) P[i]=p[i-1]*seed;
int T;
scanf ("%d", &t);
while (t--) {scanf ("%s", str);
int N=strlen (str);
for (int i=1; i<=n; i++) s[i]=s[i-1]*seed+str[i-1];
memset (ANS) (ans,0,sizeof); for (int l=1; l<=n;
l++) {h.init ();
for (int i=1; i+l-1<=n; i++) {int L=h.insert (s[i+l-1]-s[i-1]*p[l],i);
ans[i][i+l-1]++;
ans[l][i+l-1]--; for (int i=n; i>=0; i--) for (int j=i; j<=n; j + +) ans[i][j]+=ans[i+1][
J]+ANS[I][J-1]-ANS[I+1][J-1];
int Q;
scanf ("%d", &q);
while (q--) {int a,b;
scanf ("%d%d", &a,&b);
printf ("%d\n", Ans[a][b]);
} return 0; }
suffix array
#include <algorithm> #include <iostream> #include <string.h> #include <stdio.h> using namespace
Std
const int inf=0x3f3f3f3f;
const int maxn=2010;
typedef long Long LL;
Char TXT[MAXN];
int sa[maxn],t1[maxn],t2[maxn],ct[maxn],he[maxn],rk[maxn],n,m;
void Getsa (char *st) {int i,k,p,*x=t1,*y=t2;
for (i=0; i<m; i++) ct[i]=0;
for (i=0; i<n; i++) ct[x[i]=st[i]]++;
for (I=1; i<m; i++) ct[i]+=ct[i-1];
for (i=n-1; i>=0; i--) sa[--ct[x[i]]]=i;
For (K=1,p=1, p<n; k<<=1,m=p) {for (p=0,i=n-k; i<n; i++) y[p++]=i;
For (i=0 i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;
for (i=0; i<m; i++) ct[i]=0;
for (i=0; i<n; i++) ct[x[y[i]]]++;
for (I=1; i<m; i++) ct[i]+=ct[i-1];
for (i=n-1; i>=0; i--) sa[--ct[x[y[i]]]]=y[i]; for (Swap (x,y), P=1,x[sa[0]]=0,i=1 i<n; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]
? p-1:p++; } void Gethe (chAr *st) {int i,j,k=0;
for (i=0; i<n; i++) rk[sa[i]]=i;
For (i=0 i<n-1; i++) {if (k) k--;
J=SA[RK[I]-1];
while (St[i+k]==st[j+k]) k++;
He[rk[i]]=k;
int main () {int t,i,q,le,ri,lcp,ml,ans,tp;
scanf ("%d", &t);
while (t--) {scanf ("%s", txt);
N=strlen (TXT) +1;
m=150;
Getsa (TXT);
Gethe (TXT);
scanf ("%d", &q);
while (q--) {scanf ("%d%d", &le,&ri);
Le--, ri--;
ans=lcp=ml=0;
For (I=1 i<n; i++) {lcp=min (lcp,he[i]);
Ml=min (ML,LCP);
if (Sa[i]>=le&&sa[i]<=ri) {ans+=ri-sa[i]+1-min (RI-SA[I]+1,ML);
LCP=HE[I+1];
Tp=min (lcp,ri-sa[i]+1);
Ml=max (ML,TP);
} printf ("%d\n", ans); } RETUrn 0; }
suffix automata
#include <algorithm> #include <iostream> #include <string.h> #include <stdio.h> using namespace
Std
const int inf=0x3f3f3f3f;
const INT maxn=2010<<1;
typedef long Long LL;
struct Node {node *f,*ch[30];
int Len,way;
void Init () {way=0;
memset (ch,0,sizeof ch);
}}*root,*tail,sam[maxn<<1];
int tot,dp[2010][2010];
Char TXT[MAXN];
void Init () {tot=0;
root=tail=&sam[tot++];
root->f=null;
root->len=0;
Root->init ();
root->way=1;
} void Insert (int c) {node *p=tail,*np=&sam[tot++];
Np->init (),np->len=p->len+1;
while (P&&!p->ch[c]) {np->way+=p->way;
p->ch[c]=np,p=p->f;
} TAIL=NP;
if (!p) np->f=root;
else {if (p->ch[c]->len==p->len+1) np->f=p->ch[c];
else {node *q=p->ch[c],*nq=&sam[tot++];
*nq=*q; nq->len=p->len+1;
nq->way=0;
q->f=np->f=nq;
while (p&&p->ch[c]==q) {p->ch[c]->way-=p->way;
nq->way+=p->way;
p->ch[c]=nq,p=p->f;
int main () {int i,j,t,len,q,le,ri;
scanf ("%d", &t);
while (t--) {scanf ("%s", txt);
Len=strlen (TXT);
For (i=0 i<len; i++) {init ();
For (J=i j<len; j + +) {Insert (txt[j]-' a ');
dp[i][j]=tail->way;
For (j=i+1 j<len; j + +) Dp[i][j]+=dp[i][j-1];
} scanf ("%d", &q);
while (q--) {scanf ("%d%d", &le,&ri);
printf ("%d\n", dp[le-1][ri-1]);
} return 0; }