Codeforces 245H Queries for Number of Palindromes:區間dp

Leohh發表於2018-01-05

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

 

相關文章