您的位置:首页 > 其它

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

2016-07-24 10:48 447 查看

Reincarnation

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


[align=left]Problem Description[/align]
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.

[align=left]Input[/align]
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.

[align=left]Output[/align]
For each test cases,for each query,print the answer in one line.

[align=left]Sample Input[/align]

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

[align=left]Sample Output[/align]

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]]。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=4010;
int fa[maxn],ch[maxn][26];
int len[maxn],lst,cnt;
int dp[maxn][maxn];
char s[maxn];
struct Opt{
void Init(){
memset(ch,0,sizeof(ch));
lst=cnt=1;
}

int Insert(int c){
int p=lst,np=lst=++cnt;len[np]=len[p]+1;
while(p&&ch[p][c]==0)ch[p][c]=np,p=fa[p];
if(!p)fa[np]=1;
else{
int q=ch[p][c];
if(len[q]==len[p]+1)fa[np]=q;
else{
int nq=++cnt;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
}
}
return len[lst]-len[fa[lst]];
}
}SAM;
int main(){
int T,Q;
scanf("%d",&T);
while(T--){
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++){
SAM.Init();
for(int j=i;j<=len;j++)
dp[i][j]=dp[i][j-1]+SAM.Insert(s[j]-'a');
}
scanf("%d",&Q);
while(Q--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",dp[l][r]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: