-------------
Reincarnation
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 1439 Accepted Submission(s): 503
Problem Description
Now you are back,and have a task to do:
Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s.
And you have some query,each time you should calculate f(s[l...r]), s[l...r] means the sub-string of s start from l end at r.
Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s.
And you have some query,each time you should calculate f(s[l...r]), s[l...r] means the sub-string of s start from l end at r.
Input
The first line contains integer T(1<=T<=5), denote the number of the test cases.
For each test cases,the first line contains a string s(1 <= length of s <= 2000).
Denote the length of s by n.
The second line contains an 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.
For each test cases,the first line contains a string s(1 <= length of s <= 2000).
Denote the length of s by n.
The second line contains an 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 1HintI won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
Source
Recommend
zhuyuanchen520
-------------
后缀自动机啊,真是不明觉厉
-------------
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <climits>
#include <numeric>
#include <vector>
#define sz(x) int(x.size())
using namespace std;
typedef vector<int> VI;
const int maxn = 5000 + 10;
class SuffixAutomaton{
private:
struct Node{
Node *suf, *go[26];
int val;
Node(){
suf=NULL;
val=0;
memset(go,0,sizeof(go));
}
void clear(){
suf=NULL;
val=0;
memset(go,0,sizeof(go));
}
int calc(){
if (suf==0) return 0;
return val-suf->val;
}
};
Node *root,*last;
Node nodePool[maxn*2],*cur;
Node* newNode(){
Node* res=cur++;
res->clear();
return res;
}
int tot;
void extend(int w){
Node *p=last;
Node *np=newNode();
np->val=p->val+1;
while (p&&!p->go[w]){
p->go[w]=np;
p=p->suf;
}
if (!p){
np->suf=root;
tot+=np->calc();
}
else{
Node *q=p->go[w];
if (p->val+1==q->val){
np->suf=q;
tot+=np->calc();
}
else{
Node *nq=newNode();
memcpy(nq->go,q->go,sizeof(q->go));
tot-=p->calc()+q->calc();
nq->val=p->val+1;
nq->suf=q->suf;
q->suf=nq;
np->suf=nq;
tot+=p->calc()+q->calc()+np->calc()+nq->calc();
while (p&&p->go[w]==q){
p->go[w]=nq;
p=p->suf;
}
}
}
last = np;
}
public:
void init(){
cur=nodePool;
root=newNode();
last=root;
}
VI getSubString(char s[]){
VI v;
tot=0;
int len=strlen(s);
for (int i=0;i<len;i++){
extend(s[i]-'a');
v.push_back(tot);
}
return v;
}
}atm;
int ans[maxn][maxn];
char s[maxn];
int main() {
int T;
scanf("%d",&T);
while (T--){
scanf("%s",s);
int len=strlen(s);
for (int i=0;i<len;i++){
atm.init();
VI v=atm.getSubString(s+i);
for (int j=0;j<sz(v);j++) ans[i][i+j]=v[j];
}
int nQ;
scanf("%d",&nQ);
while (nQ--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",ans[l-1][r-1]);
}
}
return 0;
}
-------------
-------------
-------------
-------------
-------------