Codeforces 245H Queries for Number of Palindromes:区间dp
题目链接:http://codeforces.com/problemset/problem/245/H
题意:
给你一个字符串s。
然后有t个询问,每个询问给出x,y,问你区间[x,y]中的回文子串的个数。
题解:
表示状态:
dp[x][y] = numbers
表示区间[x,y]中的回文子串个数。
找出答案:
每次询问:ans = dp[x][y]
如何转移:
dp[x][y] = dp[x][y-1] + dp[x+1][y] - dp[x+1][y-1] + pal[x][y]
用到了容斥原理。
pal[x][y]表示子串s[x to y]是否是一个回文串(是为1,不是为0)。
其中pal[x][y]又有递推式:
pal[x][y] = ( s[x]==s[y] && (x+1==y || pal[x+1][y-1]) )
记忆化搜索就好啦。
边界条件:
if(x>y) dp[x][y] = 0
if(x==y) dp[x][y] = 1
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 5005 5 6 using namespace std; 7 8 int t; 9 int dp[MAX_N][MAX_N]; 10 int pal[MAX_N][MAX_N]; 11 char s[MAX_N]; 12 13 int is_pal(int x,int y) 14 { 15 if(s[x]!=s[y]) return 0; 16 if(x+1==y) return 1; 17 if(pal[x+1][y-1]!=-1) return pal[x+1][y-1]; 18 return pal[x+1][y-1]=is_pal(x+1,y-1); 19 } 20 21 int dfs(int x,int y) 22 { 23 if(dp[x][y]!=-1) return dp[x][y]; 24 if(x>y) return 0; 25 if(x==y) return dp[x][y]=pal[x][y]=1; 26 dp[x][y]=dfs(x,y-1)+dfs(x+1,y)-dfs(x+1,y-1); 27 pal[x][y]=(s[x]==s[y] && (x+1==y || pal[x+1][y-1])); 28 return dp[x][y]=dp[x][y]+pal[x][y]; 29 } 30 31 int main() 32 { 33 scanf("%s%d",s+1,&t); 34 memset(dp,-1,sizeof(dp)); 35 int x,y; 36 while(t--) 37 { 38 scanf("%d%d",&x,&y); 39 printf("%d\n",dfs(x,y)); 40 } 41 }