HDU 4622 后缀自动机

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy704599894/article/details/82817514

Reincarnation

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


 

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

题意:给出一个字符串和q次询问,每次询问[l,r]区间内不同子串的个数

预处理出所有区间的不同子串个数,暴力每个区间,对于每个区间的字符串构建后缀自动机求出子串个数,然后去重

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxm = 10005;
struct node
{
    int len, link;
    int Next[26];
}st[maxm];
int cnt, last, ans[2005][2005];
char str[maxm];
void init()
{
    cnt = last = 0;
    memset(st, 0, sizeof(st));
    st[cnt].link = -1;
    cnt++;
}
void insert(char ch)
{
    int p = last, now = cnt++, rev;
    st[now].len = st[last].len + 1;
    while (p != -1 && !st[p].Next[ch - 'a'])
    {
        st[p].Next[ch - 'a'] = now;
        p = st[p].link;
    }
    if (p == -1)
        st[now].link = 0;
    else
    {
        int q = st[p].Next[ch - 'a'];
        if (st[q].len == st[p].len + 1)
            st[now].link = q;
        else
        {
            rev = cnt++;
            st[rev] = st[q];
            st[rev].len = st[p].len + 1;
            while (p != -1 && st[p].Next[ch - 'a'] == q)
                st[p].Next[ch-'a'] = rev, p = st[p].link;
            st[q].link = st[now].link = rev;
        }
    }
    last = now;
}
int main()
{
    int n, i, j, k, sum, t, l, r;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%s", str + 1);
        k = strlen(str + 1);
        memset(ans, 0, sizeof(ans));
        for (i = 1;i <= k;i++)
        {
            init();
            for (j = i;j <= k;j++)
            {
                insert(str[j]);
                //printf("%d %d\n", st[last].len,last);
                ans[i][j] = ans[i][j - 1] + st[last].len - st[st[last].link].len;
            }
        }
        scanf("%d", &k);
        while (k--)
        {
            scanf("%d%d", &l, &r);
            printf("%d\n", ans[l][r]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zy704599894/article/details/82817514