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 }

 

posted @ 2018-01-05 11:37  Leohh  阅读(199)  评论(0编辑  收藏  举报