hdu 4622 Reincarnation

来源:互联网 发布:中国网络歌手排行榜 编辑:程序博客网 时间:2024/05/24 00:57


Reincarnation

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 3684    Accepted Submission(s): 1441


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
2bbaba53 42 22 52 41 4baaba53 33 41 43 55 5
 

Sample Output
3175813851
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.
 

Author
WJMZBMR
 

Source
2013 Multi-University Training Contest 3
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:  6032 6031 6030 6029 6028 





【分析】
后缀自动机第一题...
细节出错被卡成了zz...qwq
我们可以以每个位置为开头跑len编自动机,然后把用ans[i][j]记录答案,O(1)查询。
ans[i][j]=ans[i][j-1]+step[np]-step[pre[np]](防止相同的前缀子串重复计数)




【代码】
//hdu 4622 Reincarnation#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=2005;char s[mxn];int n,m,T,p,q,np,nq,len,root,last,tot;int step[mxn<<1],son[mxn<<1][30],pre[mxn<<1],ans[mxn][mxn];inline void sam(int S){    int i,j;    np=root=tot=1;    M(step),M(son),M(pre);    fo(i,S,len)    {        int c=s[i]-'a'+1;        p=np;        step[np=(++tot)]=step[p]+1;        while(p && !son[p][c])          son[p][c]=np,p=pre[p];        if(!p)        {            pre[np]=root;            ans[S][i]=ans[S][i-1]+step[np];            continue;        }         q=son[p][c];        if(step[p]+1==step[q])          pre[np]=q;        else        {            step[nq=(++tot)]=step[p]+1;            fo(j,1,26) son[nq][j]=son[q][j];            pre[nq]=pre[q];            pre[q]=pre[np]=nq;            while(p && son[p][c]==q)              son[p][c]=nq,p=pre[p];        }        ans[S][i]=ans[S][i-1]+step[np]-step[pre[np]];    }}int main(){    int i,j,l,r;    scanf("%d",&T);    while(T--)    {    M(ans);        scanf("%s",s+1);        len=strlen(s+1);        scanf("%d",&n);        fo(i,1,len) sam(i);        while(n--)        {            scanf("%d%d",&l,&r);            printf("%d\n",ans[l][r]);        }    }    return 0;}


0 0