字符串(后缀自动机):HDU 4622 Reincarnation

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
",dp[l][r]);
49         }
50     }
51     return 0;
52 }
原文地址:https://www.cnblogs.com/TenderRun/p/5700259.html