HDU 4622 Reincarnation 后缀自动机

对长度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;
}

Reincarnation

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

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.

Author

WJMZBMR

Source

2013 Multi-University Training Contest 3

Recommend

zhuyuanchen520 | We have carefully selected several similar problems for you: 5664 5663 5662 5661 5660

你可能感兴趣的:(HDU,后缀数组/自动机,离线)