题目大意

对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。

现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。

输入样例

第一行一个正整数N (N ≤ 500,000)。第二行一个长度为N的01字符串。

输出样例

一个正整数,表示反对称子串的个数。

输入样例

8

11001011

输出样例

7

题解

最简单的方法就是二分+Hash了。

我们可以想,对于每个点$i$,如果字符串$[i - j + 1...i + j]$为反对称的,则对于满足$1 \leqslant k < j$的$k$,都有字符串$[i - k + 1...i + k]$为反对称的。

根据这个单调性,我们只需要枚举$i$,然后二分$j$即可。

#include <iostream>
#include <cstdio> #define MAX_N (500000 + 5) using namespace std; typedef unsigned long long ull;
typedef const unsigned long long cull;
int n;
char s[MAX_N];
cull b = ;
ull h1[MAX_N], h2[MAX_N], pb[MAX_N];
int ans; int main()
{
scanf("%d%s", &n, s + );
pb[] = ;
for(register int i = , j = n; i <= n; ++i, --j)
{
h1[i] = h1[i - ] * b + (s[i] == '') + ;
h2[j] = h2[j + ] * b + (s[j] == '') + ;
pb[i] = pb[i - ] * b;
}
int lt, rt, mid;
for(register int i = ; i <= n; ++i)
{
lt = ;
rt = min(i, n - i);
while(lt <= rt)
{
mid = lt + rt >> ;
if(h1[i + mid] - h1[i - mid] * pb[mid << ] != h2[i - mid + ] - h2[i + mid + ] * pb[mid << ]) rt = mid - ;
else lt = mid + ;
}
ans += rt;
}
printf("%d", ans);
return ;
}

参考程序(Hash)

当然,我们也可以直接用manacher做。

其实反对称就类似回文,这里的反对称其实可以理解为对于每个字符串,左半边异或后等于右半边,我们把manacher稍微改一下即可。

注意,这里不能随枚举奇数长度的子串,因为奇数长度本身就是不可能反对称的,这样子可能会影响偶数长度子串的判断。

#include <iostream>
#include <cstdio> #define MAX_N (500000 + 5) using namespace std; int n;
char s[MAX_N];
int len;
char ns[MAX_N << ];
int p[MAX_N << ];
char to[];
long long ans; int main()
{
scanf("%d%s", &n, s + );
len = n << | ;
ns[] = '~';
ns[len + ] = '^';
ns[] = '#';
for(register int i = ; i <= n; ++i)
{
ns[i << ] = s[i];
ns[i << | ] = '#';
}
to[''] = '';
to[''] = '';
to['#'] = '#';
to['~'] = '~';
to['^'] = '^';
int rt = , mid = ;
for(register int i = ; i <= len; i += )
{
if(i < rt) p[i] = min(rt - i + , p[(mid << ) - i]);
else p[i] = ;
while(ns[i + p[i]] == to[ns[i - p[i]]]) ++p[i];
if(i + p[i] - > rt)
{
rt = i + p[i] - ;
mid = i;
}
ans += p[i] >> ;
}
printf("%lld", ans);
return ;
}

参考程序(Manacher)

最新文章

  1. C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)
  2. pthread_cond_wait()函数的理解(摘录)
  3. 【poj2122】 Optimal Milking
  4. [tp3.2.1]让默认页面: 加载Home模块的Index控制器;而让admin.php默认去加载Admin模块的Adminc控制器.
  5. CF 113C
  6. 阿里商业评论 | 互联网POI数据及其在营销中的应用
  7. android开发 PopupWindow 设置充满屏幕
  8. [OC Foundation框架 - 17] copy语法
  9. Ember.js demo5
  10. OpenGL画图旋转
  11. PHP读取EXCEL时写入数据乱码解决办法
  12. 十个最值得阅读学习的C开源项目代码
  13. 开发一个微信小程序教程
  14. Android各种Manager
  15. LeetCode - 653. Two Sum IV - Input is a BST
  16. c++ 指针总结 函数参数指针调用和堆栈内存的分配原理
  17. Tomcat内核之ASCII解码的表驱动模式
  18. Java 入门进阶
  19. android addJavascriptInterface 不能生效 解决办法
  20. DG备库,实时应用如何判断,MR进程,及MRP应用归档,三种情况的查询及验证

热门文章

  1. BUUCTF--新年快乐
  2. 攻防世界--python-trade
  3. cgi+lighttpd上传大文件失败解决办法
  4. vue 中使用 watch 出现了如下的报错
  5. Tutorial2
  6. Sass函数:列表函数nth
  7. HTML基础:用表单写一个简易登录页面
  8. Linux设备驱动详解 宋宝华 硬件基础
  9. SpringBoot中发送邮件服务
  10. https原理和如何配置https