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.
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.
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 1HintI won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
建立n个后缀自动机然后存下全部信息即可
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 2005;
class SAM
{
const static int maxn=100005; //节点个数
const static int size = 26; //字符的范围
const static char base='a'; //字符的基准
class node
{
public:
node *fa, *next[size];
int len, cnt;
node* clear(int x)
{
fa = 0; len = x; cnt = 0;
memset(next, 0, sizeof(next));
return this;
}
}nd[maxn]; //节点的设置
node *root, *last; //根节点,上一个节点
int tot; //总节点数
public:
void clear()
{
last = root = &nd[tot = 0];
nd[0].clear(0);
nd[0].cnt = 1;
} //初始化
int insert(char ch)
{
node *p = last, *np = nd[++tot].clear(p->len + 1);
last = np;
int x = ch - base;
while (p&&p->next[x] == 0) p->next[x] = np, p = p->fa;
if (p == 0) { np->fa = root; return np->cnt = np->len - np->fa->len; }
node* q = p->next[x];
if (p->len + 1 == q->len) { np->fa = q; return np->cnt = np->len - np->fa->len; }
node *nq = nd[++tot].clear(p->len + 1);
memcpy(nq->next, q->next, sizeof q->next);
nq->fa = q->fa;
q->fa = np->fa = nq;
while (p &&p->next[x] == q) p->next[x] = nq, p = p->fa;
return np->cnt = np->len - np->fa->len;
} //插入操作
}sam;
int T, n, l, r;
char s[maxn];
int f[maxn][maxn];
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%s", s);
memset(f, 0, sizeof(f));
for (int i = 0; s[i]; i++)
{
sam.clear();
for (int j = i; s[j]; j++) f[i + 1][j + 1] = f[i + 1][j] + sam.insert(s[j]);
}
scanf("%d", &n);
while (n--)
{
scanf("%d%d", &l, &r);
printf("%d\n", f[l][r]);
}
}
return 0;
}