題目連結: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 }