CF245H Queries for Number of Palindromes(dp,二维前缀和)
洛谷传送门
解题思路
先用类似dp预处理出is[l][r]表示l到r这个区间是不是回文串。
然后在把is数组放到二维平面上,每次询问l,r实际上就是询问(l,l)到(r,r)这样一个矩阵的点的数量。
可以用二维前缀和处理出来,O(1)查询。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=5005;
string s;
int n,m,dp[maxn][maxn],is[maxn][maxn];
template<class T>inline void read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
int main(){
cin>>s;
n=s.length();
for(int i=1;i<=n;i++) is[i][i]=1;
for(int i=2;i<=n;i++){
if(s[i-2]==s[i-1]) is[i-1][i]=1;
}
for(int len=3;len<n;len++){
for(int i=1;i<n;i++){
int j=i+len-1;
if(j>n) break;
if(s[i-1]==s[j-1]&&is[i+1][j-1]) is[i][j]=1;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+is[i][j];
}
}
cin>>m;
for(int i=1;i<=m;i++){
int l,r;
read(l);
read(r);
printf("%d\n",dp[r][r]-dp[l-1][r]-dp[r][l-1]+dp[l-1][l-1]);
}
return 0;
}