I-string_2019牛客暑期多校训练营(第四场)

题意
当a != b且a != rev(b)则认为a串与b串不相等,rev(b)表示b串的反串,例如rev(abcd) = dcba
给出一个串求出该串所有不相等的子串个数
题解
先利用后缀数组求出s#rev(s)的不相等子串个数,再扣掉包含字符‘#’的子串个数,包含‘#’的子串个数为\((len(s)+1)^2\),具体取法为以#及左边任意字符为起点,以#及右边字符为终点构成的串,显然这样能取出所有包含#的子串,且这些子串都不相等。
所以求出来结果是\(ans = \frac{(2len(s)+1)*(2len(s))}{2}- \sum_{i=2}^{2len(s)+1}height[i]-(len(s)+1)^2\), 这样求出来的结果是包含a = rev(b)的,比如s = abac,求出来的结果是\({a,b,c,ab,ba,ac,ca,cab,aba,bac,abac,caba}\),可以看出来除了\({a,b,c,aba}\)这几个回文串,剩余的串都是成对的,那么我们用回文树求出s本质不同的回文串个数加上之前的ans再除以2就是答案了
代码
#include <bits/stdc++.h>
const int mx = 5e5+5;
typedef long long ll;
char str[mx];
int t1[mx], t2[mx], c[mx];
int sa[mx], rank[mx], height[mx];
bool cmp(int *r, int a, int b, int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int n, int m) {
n++;
int i, j, p, *x = t1, *y = t2;
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[x[i] = str[i]]++;
for (i = 1; i < m; i++) c[i] += c[i-1];
for (i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
for (j = 1; j <= n; j <<= 1) {
p = 0;
for (i = n-j; i < n; i++) y[p++] = i;
for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[x[y[i]]]++;
for (i = 1; i < m; i++) c[i] += c[i-1];
for (i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
std::swap(x, y);
p = 1; x[sa[0]] = 0;
for (i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
if (p >= n) break;
m = p;
}
int k = 0;
n--;
for (i = 0; i <= n; i++) rank[sa[i]] = i;
for (i = 0; i < n; i++) {
if (k) k--;
j = sa[rank[i]-1];
while (str[i+k] == str[j+k]) k++;
height[rank[i]] = k;
}
}
const int N = 26;
struct pTree {
int Next[mx][N];
int fail[mx];
ll cnt[mx];
ll sum[mx];
int num[mx];
int len[mx];
int S[mx];
int last, n, p, cur, now;
int newnode(int l) {
for (int i = 0; i < N; i++) Next[p][i] = 0;
cnt[p] = num[p] = 0;
len[p] = l;
return p++;
}
void init() {
n = p = 0;
newnode(0);
newnode(-1);
last = 0;
S[n] = -1;
fail[0] = 1;
}
int getFail(int x) {
while (S[n - len[x] - 1] != S[n]) x = fail[x];
return x;
}
bool add(int c) {
S[++n] = c;
cur = getFail(last);
bool flag = false;
if (!Next[cur][c]) {
flag = true;
now = newnode(len[cur] + 2);
fail[now] = Next[getFail(fail[cur])][c];
Next[cur][c] = now;
num[now] = num[fail[now]] + 1;
}
last = Next[cur][c];
cnt[last]++;
return flag;
}
void count() {
for (int i = p-1; i >= 0; i--) cnt[fail[i]] += cnt[i];
}
}tree;
int main() {
scanf("%s", str);
int len = std::strlen(str);
str[len] = '#';
for (int i = len+1; i <= 2*len; i++) str[i] = str[2*len-i];
str[2*len+1] = '\0';
int n = 2*len+1;
da(n, 128);
ll tot = 1LL * (2*len+1) * (2*len+2)/2;
tot -= 1LL * (len+1) * (len+1);
for (int i = 2; i <= n; i++) tot -= height[i];
tree.init();
for (int i = 0; i < len; i++) tree.add(str[i]-'a');
printf("%lld\n", (tot+tree.p-2)/2);
return 0;
}
I-string_2019牛客暑期多校训练营(第四场)的更多相关文章
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 2019牛客暑期多校训练营(第二场)J-Subarray(思维)
>传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ...
- J-Subarray_2019牛客暑期多校训练营(第二场)
题意 有一个只由1,-1组成的数组,给出所有连续的1所在位置,求满足1的个数大于-1的个数的子区间的数量 题解 参考博客:https://www.cnblogs.com/Yinku/p/1122149 ...
- 2019牛客暑期多校训练营(第一场)-A (单调栈)
题目链接:https://ac.nowcoder.com/acm/contest/881/A 题意:给定两个长度均为n的数组a和b,求最大的p使得(a1,ap)和(b1,bp)等价,等价的定义为其任意 ...
随机推荐
- wangEditor富文本编辑器使用及图片上传
引入js文件 <script type="text/javascript" src="style/js/wangEditor.min.js">< ...
- Nginx 的简单使用 (IIS,Asp.Net)
Nginx 的一些常见功能(windows,AspNet ,IIS) 下载 官方网站:https://nginx.org/en/download.html 下载,解压缩是这个样子 启动: 启动方式有两 ...
- html+css+dom补充
补充1:页面布局 一般像京东主页左侧右侧都留有空白,用margin:0 auto居中,一般.w. <!DOCTYPE html> <html lang="en"& ...
- 爬虫获取搜狐汽车的配置信息 和swf动态图表的销量数据-------详细教学
前情提要:需要爬取搜狐汽车的所有配置信息,具体配置对应的参数. 以及在动态图表上的历史销量. 比如: 一汽奥迪旗下Q5L 的<40 TFSI 荣享进取型 国VI >的历史销量和该配置的参数 ...
- RocketMq中网络通信之服务端
一,Broker服务端入口(NettyServer端) 首先RocketMq网络通信采用的Netty通信.服务端主要集中在Broker中.我们先看一下Broker的启动类BrokerStartup 显 ...
- NS3中一些难以理解的常数
摘要:在NS3的学习中,PHY MAC中总有一些常数,需要理解才能修改.如帧间间隔等.那么,本文做个简单分析,帮助大家理解.针对802.11标准中MAC协议. void WifiMac::Conf ...
- ethtool工具使用实例
使用ethtool工具可以查看和修改网卡(NIC卡)设备配置,下面我们来看ethtool的具体用法. 1.显示网卡属性 ethtool命令后直接跟网卡名称,可以显示关于该网卡的属性值: # ethto ...
- java面向对象中的集合
1.学习集合的原因? A.数组是面向过程的,集合是面向对象的. B.集合是类,具备类的封装,继承,多态...超强功能. C.数组是固定长度,集合是可变长度 D.数组没办法获得真实的元素个数:集合可以. ...
- 【0806 | Day 9】三张图带你了解数据类型分类和Python深浅拷贝
一.数据类型分类 二.Python深浅拷贝
- 前端面试题集锦(一)之HTML部分
前端的发展日新月异,前端开发也早已从原来的切图套页面,变成了现在的非常复杂的技术体系,近期由于找工作,面试了很多家单位,也总结了一部分前端面试中经常会遇到的面试类型,并一一解答.主要分为HTML.CS ...