Reincarnation
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 3975 Accepted Submission(s): 1573
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
题目链接:HDU 4622
题意就是询问某段区间形成的子串其自身不同子串的个数,显然对于每一个询问做一次后缀数组不太现实$O(Q*(NlogN+N))$,那么可以参照普通求完整串的不同子串的方法来写,完整串的求法就是将后缀按照$rank$排序,然后减去相邻后缀之间的最长公共前缀值。
如果放到区间呢?就是把所有$sa$值在区间内的点选出来,然后要让这些点也按照后缀字典序升序,但是如果按照原来完整串的顺序,遍历过来选出的$rank$不一定是把区间子串做一遍$SA$求得的$rank$,那怎么办呢?分类讨论来更新从而维护实际对于区间内子串$rank$值的上升性质,我是枚举$rank$值来遍历的,可以发现合法的只有两种情况:当$sa[i] \lt sa[last\_rank]$或者$(sa[i] \gt sa[last\_rank]) \&\& (LCP(i,last\_rank) \lt len\_i)$时$i$才会大于$last\_rank$,才能用于更新,debug了很久终于造了一组区别正确与错误的数据,可以输出选中的$SA$值看看一下:
2
后缀自动机的做法就是用$ans[i][j]$表示区间$(i,j)$的答案,然后两个for暴力处理出所有答案,由于每次加入一个字母后,增加的子串个数是$L[last].len-L[L[last].pre].len$;
那么$ans[i][j] = ans[i][j-1] + L[last].len - L[L[last].pre].len$
abacababacab
10
1 7
正确答案是21,直接更新不分类讨论是23
SA代码:
1 |
|
SAM代码:
1 |
|