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;
}
posted @ 2021-09-26 08:36  尹昱钦  阅读(40)  评论(0编辑  收藏  举报