思路:设 f [ l ] [ r ] f[l][r] f[l][r]表示求解的范围,可以想到递归方程: f [ l ] [ r ] = f [ l + 1 ] [ r ] + f [ l ] [ r − 1 ] − f [ l + 1 ] [ r − 1 ] + v i s [ l ] [ r ] f[l][r]=f[l+1][r]+f[l][r-1]-f[l+1][r-1]+vis[l][r] f[l][r]=f[l+1][r]+f[l][r−1]−f[l+1][r−1]+vis[l][r],其中 v i s [ l ] [ r ] vis[l][r] vis[l][r]表示这段是否是回文,这里可以暴力N*N求,当然如果N更大,考虑hash预处理然后O(1)求。
1.记忆化
const int N = 5e3 + 5;
char s[N];
int vis[N][N];
int f[N][N];
int dfs2(int L, int R)
{
if (vis[L][R] >= 0)return vis[L][R];
if (L >= R)return vis[L][R] = 1;
if (dfs2(L + 1, R - 1) && s[L] == s[R])return vis[L][R] = 1;
return vis[L][R] = 0;
}
int dfs(int L, int R)
{
if (f[L][R] >= 0)return f[L][R];
if (L > R)return f[L][R] = 0;
if (L == R)return f[L][R] = 1;
return f[L][R] = dfs(L + 1, R) + dfs(L, R - 1) - dfs(L + 1, R - 1) + dfs2(L,R);
}
int main()
{
//freopen("in.txt", "r", stdin);
//经典dp:f[l][r]=f[l+1][r]+f[l][r-1]-f[l+1][r-1]+vis[l][r]
scanf("%s", s+1);
int len = strlen(s+1);
int q;q = in();
memset(f, -1, sizeof f);
memset(vis, -1, sizeof vis);
dfs(1, len);
while (q--)
{
int L = in(), R = in();
printf("%d\n", f[L][R]);
}
return 0;
}
2.hash
const int N = 5e3 + 5;
int f[N][N];
char s[N], t[N];
int lens, lent;
ll p1[N], p2[N], h1[N], h2[N], h3[N], h4[N];
void initbase()
{
p1[0] = p2[0] = 1;
f(i, 1, N-1)
{
p1[i] = p1[i - 1] * 377 % mod;
p2[i] = p2[i - 1] * 377 % mod2;
}
strcpy(t + 1, s + 1);//t正序
reverse(s + 1, s + lens + 1);//s倒序
for (int i = 1;i <= lens;i++)
h1[i] = (h1[i - 1] * 377 + s[i]) % mod,
h2[i] = (h2[i - 1] * 377 + s[i]) % mod2;
for (int i = 1;i <= lent;i++)
h3[i] = (h3[i - 1] * 377 + t[i]) % mod,
h4[i] = (h4[i - 1] * 377 + t[i]) % mod2;
}
ll pre_of_suf(int x, int y)
{
ll t1 = (h1[lens - x + 1] - (ll)h1[lens - y] * p1[y - x + 1] % mod + mod) % mod;
ll t2 = (h2[lens - x + 1] - (ll)h2[lens - y] * p2[y - x + 1] % mod2 + mod2) % mod2;
return t1 << 31 | t2;
}
ll suf_of_pre(int x, int y)
{
ll t1 = (h3[y] - (ll)h3[x - 1] * p1[y - x + 1] % mod + mod) % mod;
ll t2 = (h4[y] - (ll)h4[x - 1] * p2[y - x + 1] % mod2 + mod2) % mod2;
return t1 << 31 | t2;
}
int check(int L, int R)
{
if (suf_of_pre(L, R) == pre_of_suf(L, R))return 1;
return 0;
}
int dfs(int L, int R)
{
if (f[L][R] >= 0)return f[L][R];
if (L > R)return f[L][R] = 0;
if (L == R)return f[L][R] = 1;
return f[L][R] = dfs(L + 1, R) + dfs(L, R - 1) - dfs(L + 1, R - 1) + check(L,R);
}
int main()
{
//freopen("in.txt", "r", stdin);
//经典dp:f[l][r]=f[l+1][r]+f[l][r-1]-f[l+1][r-1]+vis[l][r]
scanf("%s", s+1);
int len = strlen(s+1);
lens = lent = len;
initbase();
int q;q = in();
memset(f, -1, sizeof f);
dfs(1, len);
while (q--)
{
int L = in(), R = in();
printf("%d\n", f[L][R]);
}
return 0;
}