题意:给出一个字符串,再给出k个询问,问区间里的回文子串有多少个。
题解:区间dp
问有多少个,肯定要标记
i
i
i开头
j
j
j结尾的字符串是不是回文串,用
i
s
p
[
i
]
[
j
]
isp[i][j]
isp[i][j]表示。
用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示区间有多少个回文串,包含以
i
+
1
i+1
i+1开头或者以
j
−
1
j-1
j−1结尾的回文串,以及
d
p
[
i
+
1
]
[
j
−
1
]
dp[i+1][j-1]
dp[i+1][j−1],多余减重复,那么可以得到转移方程:
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1] + isp[i][j]
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int MAXN = 5e3 + 5;
char s[MAXN];
int q, l, r, dp[MAXN][MAXN], isp[MAXN][MAXN];
int main() {
scanf("%s%d", s + 1, &q);
int len = strlen(s + 1);
for (int i = len; i >= 1; i--) {
dp[i][i] = isp[i][i] = isp[i + 1][i] = 1;
for (int j = i + 1; j <= len; j++) {
if (isp[i + 1][j - 1] && s[i] == s[j]) isp[i][j] = 1;
for (int k = i; k < j; k++) {
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1] + isp[i][j];
}
}
}
while (q--) {
scanf("%d%d", &l, &r);
printf("%d\n", dp[l][r]);
}
return 0;
}