WXH Round #16 C 回文

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WXH Round #16 C 回文相关的知识,希望对你有一定的参考价值。

3 回文(pal.c/cpp/pas)
3.1 题目描述
  闲着无聊的YGH秒掉上面两道题之后,开始思考有趣的回文串问题了。
  他面前就有一个漂浮着的字符串。显然YGH是会manacher的,于是他随手求出了这个字符串的回文子串个数。但是他不满足于这个问题,他打算搞出一个数据结构,能够快速求出这个字符串下标为[l,r]的子串的回文子串个数(相同的回文子串需重复计数)。但是这实在是太简单啦,他打算考考辣鸡YYR,可是辣鸡至极的YYR完全没有思路。
于是,YGH扬长而去,在衣袖带起的一小片尘土之中,沉思的YYR依旧在那里。
3.2 输入格式
  第一行为一个字符串S。
  第二行一个整数T,表示询问次数。
  接下来T行,每行两个整数l、r,表示查询字符串S下标为[l,r]的子串的答案。
3.3 输出格式
  输出T行,每行一个整数表示这个询问的答案。
3.4 样例输入
ababaab
2
1 3
3 7
3.5 样例输出
4
8
6
3 .6 数据范围与约定
对于20%的数据,保证 |S| , T<=500
对于40%的数据,保证 |S| , T <=5000
对于100%的数据,保证 |S| <=5000 , T<=100000


   啊啊啊啊啊。这道题显然是O(n^2)的,然而考试时并没有看出来……也是,数据太水暴力也过了(YYR哭晕)。

  当时以为是线段树,发现不行。又看了看分块,发现又不行。后来才明白,就是那个什么DP了。

  最开始,f[i][j]表示子串ij是否是回文串。然后进行统计,f[i][j]表示以j结尾的回文串数目(j固定,i从j开始左移)。然后再统计,f[i][j]就是i到j的回文串数目了(i固定,j从i开始右移)。这三个阶段都很好做,O(n^2)的空间,O(n^2)的预处理,O(1)的查询。

  其实不难,但确实非常经典。

 1 #define PN "pal"
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <map>
 6 const int L = 5000 + 5;
 7 int n, f[L][L];
 8 char s[L];
 9 int main() {
10     freopen(PN".in","r",stdin);
11     freopen(PN".out","w",stdout);
12     int q, lf, rg;
13     scanf("%s%d",s+1,&q);n=strlen(s+1);
14     for( int k = 1, i, j; k <= n; k++ ) {
15         i = k, j = k;
16         while(1<=i&&j<=n&&s[i]==s[j]) f[i][j]=1, i--, j++;
17         i = k, j = k+1;
18         while(1<=i&&j<=n&&s[i]==s[j]) f[i][j]=1, i--, j++;
19     }
20     for( int j = 1; j <= n; j++ ) for( int i = j; i >= 1; i-- ) f[i][j]+=f[i+1][j];
21     for( int i = 1; i <= n; i++ ) for( int j = i; j <= n; j++ ) f[i][j]+=f[i][j-1];
22     while(q--) {
23         scanf("%d%d",&lf,&rg);
24         printf("%d\n",f[lf][rg]);
25     }
26     return 0;
27 }

以上是关于WXH Round #16 C 回文的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #360 B

“玲珑杯”算法比赛 Round #14题目与标程

代码题(16)— 回文

Codeforces Round #336 (Div. 2) D. Zuma(区间DP)

Codeforces Global Round 7D(马拉车/PAM,回文串)

Codeforces Round #538 (Div. 2) D. Flood Fill 区间dp || LPS (最长回文序列)