1. 程式人生 > 其它 >CodeForces - 245H Queries for Number of Palindromes

CodeForces - 245H Queries for Number of Palindromes

區間dp、迴文子串

題意:給定一個字串,求區間[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; }
View Code