CodeForces - 245H Queries for Number of Palindromes
Posted on 2021-12-27 20:22 Capterlliar 阅读(32) 评论(0) 编辑 收藏 举报题意:给定一个字符串,求区间[l,r]内有多少回文子串。
解:回文杀我。区间dp++
首先这玩意不能像前缀和一样[l,r]=[1,r]-[1,l-1]。
那就直接设dp[i][j]为[i,j]中回文子串的数量。
考虑拿小的拼大的。如果两端不等,
dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];
如果相等在此基础上加一。有空补补容斥原理。
然后是遍历的顺序。区间dp从小区间到大区间,这题因为只有相邻两个之间可以谈转移,所以两重循环就够了。区间长度为2的时候特判一下,因为vis[i+1][j-1]会没有orz
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 5005 #define eps 0.00000001 #define inf 0x3f3f3f3f #define mod 1000000007 //#define int long long char s[maxx]; int dp[maxx][maxx]={0}; int vis[maxx][maxx]={0}; signed main() { scanf("%s",s+1); int n=strlen(s+1); for(int i=1;i<=n;i++){ dp[i][i]=1; vis[i][i]=1; } for(int len=2;len<=n;len++){ for(int i=1;i<=n-len+1;i++){ int j=i+len-1; dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]; if((len!=2&&vis[i+1][j-1]&&s[i]==s[j])||(len==2&&s[i]==s[j])){ vis[i][j]=1; dp[i][j]++; } } } int q; scanf("%d",&q); while(q--){ int l,r; scanf("%d%d",&l,&r); printf("%d\n",dp[l][r]); } return 0; }