字符串(后缀自动机):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; }
相关文章推荐
- 你当我想写“垃圾代码”吗?
- C#关键字—yield
- AC again
- C语言中 fp = fopen(filename, “rb”); 那个rb是什么意思啊
- 使用 supervisor 管理进程
- 数据驱动测试一:使用TestNG进行数据驱动
- PHP函数之array_key_exists
- csdn待改进点之34------>为什么会又在乱跳转? 请不要说重现不了!
- Swift类型推测在可选调用中的小提示
- Swift类型推测在可选调用中的小提示
- Swift类型推测在可选调用中的小提示
- CSS技巧(一):清除浮动
- 学习与记忆
- Discuz! 更改用户名长度(代码和数据库字段)
- 150. Evaluate Reverse Polish Notation
- poj2403 模拟题目
- 多线程 —— 使用锁编写线程安全的程序
- 快排为什么那么快
- Hadoop--The Definitive Book_4th Contents
- Pycharm Professional 激活服务器