对长度2000的字符串 1W次询问区间的子串个数。
发现长度很小, O(n2) ?
发现由于后缀自动机是在线构造,因此所有的区间可以按左端点排序,右端点在线。。然后子串个数维护一下SAM的总子串数就好了。。
#include
#include
#include
using namespace std;
#define FOR(i,j,k) for(i=j;i<=k;++i)
const int rt = 1, N = 4005;
int last = 1, cnt = 1, len = 0, sum = 0;
int ch[N][26], fa[N], ma[N], rr[N], b[N], bucket[N/2], ans[N/2][N/2];
char str[N/2];
void add(char c) {
#define get(i) (fa[i]?(ma[i]-ma[fa[i]]):0)
int np = ++cnt, p = last, q, nq; last = np; ma[np] = ++len; rr[np] = 0;
memset(ch[np], 0, sizeof ch[np]);
while (p && !ch[p][c]) ch[p][c] = np, p = fa[p];
if (!p) fa[np] = rt;
else {
q = ch[p][c];
if (ma[q] == ma[p] + 1) fa[np] = q;
else {
nq = ++cnt; memcpy(ch[nq], ch[q], sizeof ch[q]);
sum -= get(p) + get(q);
ma[nq] = ma[p] + 1; rr[nq] = 0;
fa[nq] = fa[q]; fa[q] = fa[np] = nq;
sum += get(p) + get(q) + get(nq);
while (p && ch[p][c] == q) ch[p][c] = nq, p = fa[p];
}
}
sum += get(np);
}
int main() {
int i, n, j, t, l, r, q;
scanf("%d", &t);
while (t--) {
scanf("%s", str + 1); n = strlen(str + 1);
FOR(i,1,n) {
last = rt; cnt = 1; len = sum = 0;
memset(ch[rt], 0, sizeof ch[rt]);
FOR(j,i,n) add(str[j] - 'a'), ans[i][j] = sum;
}
scanf("%d", &q);
while (q--) {
scanf("%d%d", &l, &r);
printf("%d\n", ans[l][r]);
}
}
return 0;
}
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.
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,for each query,print the answer in one line.
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
3
1
7
5
8
1
3
8
5
1
I won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
WJMZBMR
2013 Multi-University Training Contest 3
zhuyuanchen520 | We have carefully selected several similar problems for you: 5664 5663 5662 5661 5660