HDU 4622 Reincarnation SAM
-------------
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; }
-------------
-------------
-------------
-------------
-------------