标签:3.2 clu 个数 数据 == printf div 子串 mic
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 }
标签:3.2 clu 个数 数据 == printf div 子串 mic
原文地址:http://www.cnblogs.com/Doggu/p/floj592.html