Reincarnation
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 3194 Accepted Submission(s): 1184
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.
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.
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
Hint
I won‘t do anything against hash because I am nice.Of course this problem has a solution that don‘t rely on hash.
程立杰出的题目?
sam有个性质就是对于新加一个字符,产生的新子串个数为len[lst]-len[fa[lst]]。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=4010; 6 int fa[maxn],ch[maxn][26]; 7 int len[maxn],lst,cnt; 8 int dp[maxn][maxn]; 9 char s[maxn]; 10 struct Opt{ 11 void Init(){ 12 memset(ch,0,sizeof(ch)); 13 lst=cnt=1; 14 } 15 16 int Insert(int c){ 17 int p=lst,np=lst=++cnt;len[np]=len[p]+1; 18 while(p&&ch[p][c]==0)ch[p][c]=np,p=fa[p]; 19 if(!p)fa[np]=1; 20 else{ 21 int q=ch[p][c]; 22 if(len[q]==len[p]+1)fa[np]=q; 23 else{ 24 int nq=++cnt;len[nq]=len[p]+1; 25 memcpy(ch[nq],ch[q],sizeof(ch[q])); 26 fa[nq]=fa[q];fa[q]=fa[np]=nq; 27 while(ch[p][c]==q)ch[p][c]=nq,p=fa[p]; 28 } 29 } 30 return len[lst]-len[fa[lst]]; 31 } 32 }SAM; 33 int main(){ 34 int T,Q; 35 scanf("%d",&T); 36 while(T--){ 37 scanf("%s",s+1); 38 int len=strlen(s+1); 39 for(int i=1;i<=len;i++){ 40 SAM.Init(); 41 for(int j=i;j<=len;j++) 42 dp[i][j]=dp[i][j-1]+SAM.Insert(s[j]-‘a‘); 43 } 44 scanf("%d",&Q); 45 while(Q--){ 46 int l,r; 47 scanf("%d%d",&l,&r); 48 printf("%d\n",dp[l][r]); 49 } 50 } 51 return 0; 52 }