题目描述

长度为偶数的回文串被称为偶回文串。如果一个字符串重新排序之后能够成为一个偶回文串,则称为可回文的。

给一个字符串,求可回文的子串个数。字符串只含小写字母,单个字符串长度不超过10^5,所有数据字符串长度之和不超过2*10^6。

时间限制:3000ms   内存限制:131072kb

解题思路

由于可以重新排序,所以一个子串只要任一字母出现偶数次即可。于是将字母编号,h(c) = ±1 << (c - 'a'),第奇数次出现为正,第偶数次出现为负。于是问题转化为求某一子区间的编号和为0,维护前缀和Sum[i],又把问题转化为求相同的前缀和的点。这个时候就发现问题非常简单了,直接把Sum排序就好了。如果有x个点的Sum值相同,则对应x*(x-1)/2个合法区间,从前往后扫描完排序后的Sum数组即可得到答案。

有个小技巧:Sum排序时多加入一个0,就不用特判整个串是不是可回文的。

时间复杂度:O(n logn)

附:c++代码

 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5
6 using namespace std;
7 #define MaxLen 100020
8
9 typedef long long llt;
10 typedef unsigned long long ullt;
11
12 llt a[MaxLen], Sum[MaxLen];
13 char s[MaxLen];
14 bool vis[30];
15
16 int main()
17 {
18 //freopen("L.in", "r", stdin);
19 llt i, Len, pos;
20 ullt tmp, ans;
21 while(scanf("%s", s) != EOF)
22 {
23 memset(vis, false, sizeof(vis));
24 Len = strlen(s);
25 Sum[0] = 0;
26 for(i = 1; i <= Len; i++)
27 {
28 tmp = s[i - 1] - 'a';
29 if(vis[tmp])
30 {
31 a[i] = -(1 << tmp);
32 vis[tmp] = false;
33 }
34 else
35 {
36 a[i] = 1 << tmp;
37 vis[tmp] = true;
38 }
39 Sum[i] = Sum[i - 1] + a[i];
40 }
41 sort(Sum, Sum + Len + 1);
42 ans = 0;
43 for(i = 0; i <= Len; i++)
44 {
45 if(i == 0)
46 {
47 pos = 0;
48 continue;
49 }
50 if(Sum[i] != Sum[pos])
51 {
52 tmp = i - pos;
53 ans += tmp * (tmp - 1) / 2;
54 pos = i;
55 }
56 }
57 tmp = i - pos;
58 ans += tmp * (tmp - 1) / 2;
59 //ans += (i - pos) * (i - pos - 1) / 2;
60 //printf("%lld\n", ans);
61 cout << ans << endl;
62 }
63 return 0;
64 }

另一种思路

这是官方给出的题解。

任意一个子串里某个字符的出现次数可以被表示成两个前缀字符串里出现次数的差,例如abbababbabbab的子串ababba,就可以表示成abbababba和abb的差,如果这两个前缀串里任意一个字符出现的次数在模2意义下是相等的,那么他们的差对应的子串就是一个合法的解。 以第i个字符结尾的前缀串和以第i+1个字符结尾的前缀串只差一个字符,可以通过线性递推得到所有的前缀串的26个字符出现次数的奇偶性,可以发现每个前缀串对应26个不是0就是1的数字,可以将其压缩成一个二进制数字si,si的第k位对应第k个字符出现次数的奇偶性,添加一个字符可以利用二进制不进位加法,其中二进制不进位加法可以用异或(xor)来表示。

题目链接:https://biancheng.love/contest-ng/index.html#/29/problems

[题解]第十一届北航程序设计竞赛预赛——L.偶回文串的更多相关文章

  1. [题解]第十一届北航程序设计竞赛预赛——I.神奇宝贝大师

    题目描述 一张n*m的地图,每个格子里面有一定数量的神奇宝贝,求一个最优位置,使得所有神奇宝贝到该位置的曼哈顿距离最小. 一共有T组数据,每组数据包含两行,第一行是n和m(1<=n,m<= ...

  2. [题解]第十一届北航程序设计竞赛预赛——H.高中数学题

    题目描述 解题思路 可以求得通项公式:an = 2n + 1,所以问题就变成等差数列求异或和,这个具体为什么对我还不能很好地解释清楚,先挖坑吧. 附:c++代码 1 #include <iost ...

  3. [题解]第十一届北航程序设计竞赛预赛——F.序列

    题目描述 (1,--,n)的一个排列S,定义其对应的权值F[S]为:将S划分为若干段连续子序列,每个子序列都是上升序列,F[S]的值等于能划分出的最小段数. 求n的全排列的F[S]的和,答案mod(1 ...

  4. [题解]第十一届北航程序设计竞赛预赛——D.最大公约数

    题目描述 给一个长度为n(1<=n<=100000)的正整数列,分成尽量多的非空段,使得每一段的最大公约数相等.一个数的最大公约数是它本身. 解题思路 要求每一段子列的gcd相等,不妨设为 ...

  5. [题解]第十一届北航程序设计竞赛预赛——A.模式

    题目描述 输入一个学号,判断是计算机系or软件学院or其他院系. 解题思路 水题,直接判断or除以10000都可以.不废话,直接上代码. 1 #include <iostream> 2 # ...

  6. B P5 第十三届北航程序设计竞赛预赛

    https://buaacoding.cn/contest-ng/index.html#/188/problems 其实这题挺简单的. 注意到答案的大小最多是22 二分,check长度是mid的不同子 ...

  7. 小L的项链切割 (回文串)

    题目描述 小T送给了小L了一串项链.为了方便,我们把项链上形态不同钻石用不同的字母表示.这样小L的项链就变成了一个字符串.小L忽然想把这串项链优美地切割一下,她想把它切割成尽量少的回文项链,啊也就是回 ...

  8. 【题解】Luogu P4324 [JSOI2016]扭动的回文串

    原题传送门 这题实际挺水的 先对两个字符串分别跑马拉车 就能求出1.2类扭动回文串最大的长度 考虑第三类的扭动回文串\(S(i,j,k)\),一定可以表示为\(A(i,l)+A(l+1,j)+B(j, ...

  9. 【题解】APIO2014回文串

    哇哦~想不到我有生之年竟然能够做出字符串的题目ヾ(✿゚▽゚)ノ虽然这题比较裸但依然灰常开心! 首先有一个棒棒的性质:本质不同的回文串最多有 O(n) 个.首先 manacher 把它们都找出来,然后问 ...

随机推荐

  1. Rust 实现一个简单的区块链

    一.背景 近期用 Rust 实现了 Jeiwan/blockchain_go,与原项目相比没有加入新的功能,只是换了一个编程语言实现了一遍,源码放在 Github 上. 开发这个项目,花费了好几个周末 ...

  2. winform设置所有窗体统一图标

    class WindowHookerManager { static WindowHooker hooker = new WindowHooker(); public static void SetA ...

  3. 华为matebook x pro蓝屏和拆机更换固态硬盘

    华为老版本的笔记本电脑现在总是蓝屏. 情况 原因 我个人认为是建兴的固态硬盘的缘故. 我的笔记本几乎没用过,因为考研.如果玩游戏使用的老ThinkPad S5.matebook我这个丐版因为没有独立显 ...

  4. 科技爱好者周刊(第 175 期):知识广度 vs 知识深度

    这里记录每周值得分享的科技内容,周五发布. 本杂志开源(GitHub: ruanyf/weekly),欢迎提交 issue,投稿或推荐科技内容. 周刊讨论区的帖子<谁在招人?>,提供大量程 ...

  5. Typora基础快捷键使用流程

    Typora简介 Typora是一个所见即所得的Markdown格式文本编辑器,支持windows.macOS和GNU\Linux操作系统,包括对GitHub Flavored Markdown扩展格 ...

  6. Discriminative Learning of Deep Convolutional Feature Point Descriptors 论文阅读笔记

    介绍 该文提出一种基于深度学习的特征描述方法,并且对尺度变化.图像旋转.透射变换.非刚性变形.光照变化等具有很好的鲁棒性.该算法的整体思想并不复杂,使用孪生网络从图块中提取特征信息(得到一个128维的 ...

  7. jstl split 分割字符串?

    1. 在已经获得数据的前提下,对数据进行分割,分割后的结果是一个数组,可以通过数组获得我们需要的数据 2. value 是获得值 需要${} 的方式获取, var 是设置变量. var = " ...

  8. contos 6.9 和 centos7 配置docker?

    一.contos 6.9 配置docker? 1.检查centos的内核,因为目前docker的版本所支持的centos最低内核版本为2.4 // uname -r // 2.6.32-696.el6 ...

  9. APC 篇——总结与提升

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  10. 新手应该如何学习 PHP 语言?

    其实php开发,不只是一个简单的php开发,而是整个一个行业,一般叫web开发,或者php后端开发,所以从html,css,js,jq,php,sql基本这些都要有了解.当然你有html,css基础, ...