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 }
时间: 2025-01-03 21:41:10

WXH Round #16 C 回文的相关文章

初级算法-16. 验证回文字符串

题目描述: 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: false 一种解法是将字符串的有效字符存入数组中,再去比较 1 class Solution { 2 public boolean isPalindrome(Stri

代码题(16)— 回文(1)

1.9. 回文数 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false 解释: 从左向右读, 为 -121 . 从右向左读, 为 121- .因此它不是一个回文数. 示例 3: 输入: 10 输出: false 解释: 从右向左读, 为 01 .因此它不是一个回文数. class Solution { public: bool isPalindrome(int x)

用c#判断回文数和降序数

题目:编一个程序,输入一个正整数,判定它是否为回文数和降序数.当输入的数为0时,则退出程序,否则继续循环执行程序. 所谓“降序数”是指一个自然数的低位数字不大于高位数字的数.例如: 64, 55, 321都认为是降序数,但是623不是降序数.一位数字被认为是降序数. 所谓“回文数”是指读一个自然数,从正方向读和反方向读,结果是一样的.例如: 646,1551,891232198都认为是回文数. 具体实现代码如下: 1 string str; 2 bool a = true, b = true;/

Codeforces Round #427 (Div. 2) D. Palindromic characteristics(Manacher求回文串)

题目链接:Codeforces Round #427 (Div. 2) D. Palindromic characteristics 题意: 给你一个串,定义k-th回文串,让你求每个k-th的数量. 题解: manacher处理好后做一下dp就行了. 当然也可以直接dp不用manacher. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 cons

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

1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 int maxi,R,pos,ans_pos,p[2000007]; 5 string str,ans_str,tmp; 6 void Manacher(string s){//马拉车模板,p数组存放当前位置为轴回文串的最大长度 7 int siz=s.size(); 8 memset(p,0,sizeof(int[siz]));

YZOI Easy Round 2_回文串 string

原文链接:http://laphets1.gotoip3.com/?id=18 Description 给出一个由小写字母组成的字符串,其中一些字母被染黑了,用?表示.已知原来的串不是 一个回文串,现在让你求出字典序最小的可能的串.像’a’,’aba’,’abba’这样对称的串叫做回 文串. 每个测试点有5 组小测试点. Input 5 行,5 个字符串. Output 5 行,5 个字符串.若无解,输出”Orz,I can not find it!” 这个题目主要就是利用了一种贪心的思想  总

Codeforces Round #315 -Primes or Palindromes?(回文&amp;&amp;素数)

题目地址:Primes or Palindromes? 题意:给出p,q,A=p/q,求找出最大的n使得n以内的素数的个数<=A*n以内的回文串的个数. 思路:其实就是n以内的素数的个数*q<=n以内的回文串的个数*p.然而p/q的最大值为42,那么数到13000000就到达极限,所以我们直接可以从大的开始往小的一步一步的暴力枚举就可以(感觉窝还是太年轻..QAQ #include <stdio.h> #include <math.h> #include <str

最少回文串--牛客网(秋招备战专场三模)-C++方向

题目描述:一个字符串从左向右和从右向左读都完全一样则是回文串,给定一个字符串,问该字符串中的字符所能组成的最少的回文串的个数为多少 解题思路:如果一个字符出现的次数为偶数,则必能组成回文串,如果一个字符出现奇数次,只能自己组成回文串,题目中问最少的回文串数目,即求出现次数为奇数次的字符个数即可,定义a存储每个字符出现的次数,统计出现奇数次的字符的个数,即为输出 1 #include <iostream> 2 #include <string> 3 using namespace s

回文判断

一个整形数是否是回文 also leetcode 9 Palindrome Number要求空间复杂度O(1)按位判断一般是/和%的游戏,首先取首位 a/h (h是最接近a的10的次方,比如12321,h预计算出是10000), 再取末位a%10; 比较首位和末位是否相等,不等就返回false; 如图: 然后舍弃掉已经比较过的两个位数,从a中去掉首尾 12321 --> 232. a = a % h; // 去掉首 a = a /10; //去掉尾 h = 100; // 因为已经去掉了两位 如