题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622
题目要求处理出询问的从i到j的子串的不同子串的数量,因为串长最大2000,所以n^2+记忆化处理出任意从i到j的不同子串数量(即每个节点的max-其父节点的max)
#include<bits/stdc++.h>
#include<iostream>
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
//const int MAXN = 4e5+10;
//const int LetterSize = 26;
//
//int tot, last,ch[MAXN][LetterSize],fa[MAXN],len[MAXN];
//int ans=0;
//void init()
//{
// last = tot = 1;
// len[1] = 0;
// memset(ch,0,sizeof ch);
// memset(fa,0,sizeof fa);
// ans=0;
//}
//
//int add( int x)
//{
// int p = last, np = last = ++tot;
// len[np] = len[p] + 1;
// while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
// if(p == 0) fa[np] = 1;
// else
// {
// int q = ch[p][x];
// if( len[q] == len[p] + 1)
// fa[np] = q;
// else
// {
// int nq = ++tot;
// memcpy( ch[nq], ch[q], sizeof ch[q]);
// len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
// while( p && ch[p][x] == q) ch[p][x] = nq, p = fa[p];
// }
// }
// ans+=len[last]-len[fa[last]];
// return ans;
//}
char s[2010];
int dp[2010][2010];
typedef long long ll;
const int maxn = 4005;
const int SIGMA_SIZE = 26;
int sz, last;
int g[maxn<<1][SIGMA_SIZE], pre[maxn<<1], step[maxn<<1];
int tot;
void newNode(int s) {
step[++sz] = s;
pre[sz] = 0;
memset(g[sz], 0, sizeof(g[sz]));
}
int idx(char ch) { return ch -'a'; }
void init() {
tot = 0;
sz = 0, last = 1;
newNode(0);
}
int insert(char ch) {
newNode(step[last] + 1);
int v = idx(ch), p = last, np = sz;
while (p && !g[p][v]) {
g[p][v] = np;
p = pre[p];
}
if (p) {
int q = g[p][v];
if (step[q] == step[p] + 1)
pre[np] = q;
else {
newNode(step[p] + 1);
int nq = sz;
for (int j = 0; j < SIGMA_SIZE; j++) g[nq][j] = g[q][j];
pre[nq] = pre[q];
pre[np] = pre[q] = nq;
while (p && g[p][v] == q) {
g[p][v] = nq;
p = pre[p];
}
}
} else
pre[np] = 1;
tot += step[np] - step[pre[np]];
last = np;
return tot;
}
int main()
{
int q,n,l,r;
int t;
scanf("%d",&t);
while(t--)
{
lan(dp,0);
scanf("%s",s);
n=strlen(s);
for(int i=0;i<n;i++)
{
init();
for(int j=i;j<n;j++)
{
dp[i+1][j+1]+=insert(s[j]);
// cout <<i+1 << " " << j+1 << "= "<< dp[i+1][j+1] << endl;
}
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&l,&r);
printf("%d\n",dp[l][r]);
}
}
return 0;
}