CodeForces 245H Queries for Number of Palindromes (区间DP)
<题目链接>
题目大意:
给定字符串$S(|S|<=5000)$,下标由1开始。然后q个问题$(q\leq10^6)$,对于每个问题,给定L,R,回答区间[L,R]里有多少个回文串。
解题分析:
先预处理出任意区间的字符串是否是回文串,然后就是用区间DP,对每个区间,根据它的子区间的状态进行转移,这里要用到容斥的思想统计一下该区间回文子串的个数。$$dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+pali[i][j]$$
#include <bits/stdc++.h> using namespace std; const int N = 5e3+5; bool pali[N][N]; int dp[N][N]; char str[N]; int main(){ scanf("%s",str+1); int n=strlen(str+1); for(int i=1;i<=n;i++)pali[i][i]=1,dp[i][i]=1; for(int i=n;i>=1;i--){ for(int j=i+1;j<=n;j++){ if(str[i]==str[j] && j-i==1)pali[i][j]=1; //特判一下长度为2的区间 else if(str[i]==str[j] && pali[i+1][j-1])pali[i][j]=1; } }//先用简单的区间DP,预处理出所有区间的子串是否是回文串 for(int i=n;i>=1;i--){ for(int j=i+1;j<=n;j++){ dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+pali[i][j]; //用容斥进行该区间内回文子串数量的统计 } } int q;scanf("%d",&q); while(q--){ int l,r;scanf("%d%d",&l,&r); printf("%d\n",dp[l][r]); } }
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。