2019牛客暑期多校训练营(第四场)I - String (后缀自动机+回文树)
题目链接
题意
给一个字符串,求字符串子串的最大集合,集合中字符串互不相等,相等的定义为:a≠ba =\not ba≠b 而且 a≠rev(b)a =\not rev(b)a≠rev(b)
例如字符串abacabacabac,最大不相等集合 {abac,b,a,ab,aba,bac,ac,c}\{ abac,b,a,ab,aba,bac,ac,c\}{abac,b,a,ab,aba,bac,ac,c}
思路
我们可以将字符串SSS改为S+#+rev(S)S + \# + rev(S)S+#+rev(S),对于这个新字符串可以用Sam求出不包含#\##的子串的种类数
- S≠rev(S)S =\not rev(S)S≠rev(S)的子串就会计算两次
- S=rev(S)S = rev(S)S=rev(S)的子串就会计算一次,这个刚好是回文串
所以Sam计算的种类数加上所有的回文数就是ans×2ans × 2ans×2
如何计算不包含#\##的子串?
- 所有子串 - 包括#\##的字串 (len+1)2(len + 1)^2(len+1)2
- 对Sam进行拓扑排序,按照有效边进行转移
#include <bits/stdc++.h>
const int maxn = 4e5 + 5;
using namespace std;
struct SAM{int trans[maxn<<1][27], slink[maxn<<1], maxlen[maxn<<1];int indegree[maxn<<1], endpos[maxn<<1], rank[maxn<<1];int last, now, root, len;inline void newnode (int v) {maxlen[++now] = v;}inline void extend(int c) {newnode(maxlen[last] + 1);int p = last, np = now;// 更新transwhile (p && !trans[p][c]) {trans[p][c] = np;p = slink[p];}if (!p) slink[np] = root;else {int q = trans[p][c];if (maxlen[p] + 1 != maxlen[q]) {// 将q点拆出nq,使得maxlen[p] + 1 == maxlen[q]newnode(maxlen[p] + 1);int nq = now;memcpy(trans[nq], trans[q], sizeof(trans[q]));slink[nq] = slink[q];slink[q] = slink[np] = nq;while (p && trans[p][c] == q) {trans[p][c] = nq;p = slink[p];} }else slink[np] = q;}last = np;// 初始状态为可接受状态endpos[np] = 1;}inline void build(char *s) {root = last = now = 1;for (int i = 0; s[i]; ++i) extend(s[i] - 'a'); // extend(s[i] - '1');}inline long long getNum() {long long ans = 0;for (int i = 2; i <= now; ++i) {ans += maxlen[i] - maxlen[slink[i]];}return ans;}
}sam;
struct Palindrome_Tree{int nex[maxn][26];int fail[maxn], cnt[maxn], num[maxn]; // num 记录每个节点右端点的表示回文串的个数int len[maxn], S[maxn]; // cnt 记录每个节点表示的回文串出现的次数int last, n, p;int newnode(int l) { // 新建节点for (int i = 0; i < 26; ++i) nex[p][i] = 0;cnt[p] = num[p] = 0;len[p] = l;return p++;}void init() { // 初始化p = 0;newnode(0), newnode(-1); // 新建奇根和偶根last = n = 0;S[n] = -1; fail[0] = 1; // 偶根指向}int get_fail(int x) { // 求failwhile (S[n - len[x] - 1] != S[n]) x = fail[x];return x;}void add(int c) { // 添加节点c -= 'a';S[++n] = c;int cur = get_fail(last);if (!nex[cur][c]) {int now = newnode(len[cur] + 2);fail[now] = nex[get_fail(fail[cur])][c];nex[cur][c] = now;num[now] = num[fail[now]] + 1;}last = nex[cur][c];cnt[last]++;}void count() { // 求cntfor (int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i];}
}Tree;
char s[maxn];
int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);scanf("%s", s);Tree.init();int len = strlen(s);s[len] = 26 + 'a';for (int i = 0; i < len; ++i) {Tree.add(s[i]);s[i+len+1] = s[len-i-1];}s[len+len+1] = 0;sam.build(s);long long ans = (sam.getNum() - 1ll * (len+1) * (len+1) + Tree.p - 2) / 2;printf("%lld\n", ans);return 0;
}
2019牛客暑期多校训练营(第四场)I - String (后缀自动机+回文树)相关推荐
- 【2019牛客暑期多校训练营(第二场)- E】MAZE(线段树优化dp,dp转矩阵乘法,线段树维护矩阵乘法)
题干: 链接:https://ac.nowcoder.com/acm/contest/882/E?&headNav=acm 来源:牛客网 Given a maze with N rows an ...
- 2019牛客暑期多校训练营(第九场)H Cutting Bamboos(主席树+二分)
链接:https://ac.nowcoder.com/acm/contest/889/H 来源:牛客网 题目描述 There are n bamboos arranged in a line. The ...
- 【2019牛客暑期多校训练营(第二场) - H】Second Large Rectangle(单调栈,全1子矩阵变形)
题干: 链接:https://ac.nowcoder.com/acm/contest/882/H 来源:牛客网 题目描述 Given a N×MN \times MN×M binary matrix. ...
- 2019牛客暑期多校训练营(第一场)E-ABBA(dp)
链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...
- 2019牛客暑期多校训练营(第一场)
传送门 参考资料: [1]:官方题解(提取码:t050 ) [2]:标程(提取码:rvxr ) [3]:牛客题解汇总 A.Equivalent Prefixes(单调栈) •题意 定义两个数组 u,v ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 【2019牛客暑期多校训练营(第二场)- F】Partition problem(dfs,均摊时间优化)
题干: 链接:https://ac.nowcoder.com/acm/contest/882/F 来源:牛客网 Given 2N people, you need to assign each of ...
- 【2019牛客暑期多校训练营(第二场) - D】Kth Minimum Clique(bfs,tricks)
题干: 链接:https://ac.nowcoder.com/acm/contest/882/D 来源:牛客网 Given a vertex-weighted graph with N vertice ...
- 【2019牛客暑期多校训练营(第一场) - A】Equivalent Prefixes(单调栈,tricks)
题干: 链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Two arrays u and v each with m distinct elem ...
- 【2019牛客暑期多校训练营(第一场) - H】XOR(线性基,期望的线性性)
题干: 链接:https://ac.nowcoder.com/acm/contest/881/H 来源:牛客网 Bobo has a set A of n integers a1,a2,-,ana1, ...
最新文章
- session过期重新登陆_深入分析Session和Cookie-前端面试题
- linux学习-用户的特殊 shell 与 PAM 模块
- 台湾印象之三:吃与喝
- python中decode的用法_python中list怎么使用decode方法设置编码
- 深入理解Mysql - 事务与锁原理
- python在原有的字符串的基础上追加列表构成的字符串,并保持格式一致
- 【Elasticsearch】Elasticsearch Span Query跨度查询
- 【报告分享】中国营销数字化行业趋势报告:全渠道时代,品牌商如何抓住消费者?(附下载链接)...
- oracle删除数据释放表空间流程
- c语言的课本答案,c语言课本试题答案
- Convirt管理机Socat驻留进程故障处理
- tensorflow2.0内存溢出解决办法
- hi3559AV100上交叉编译faiss(facebook research)
- WDSR:Wide Activation for Efficient and Accurate Image Super-Resolution
- 几本开关电源书籍 pdf格式 (来源中国电子开发网)
- 80后年轻老板创业心经
- iTop4412---linux 3.0.15内核编译错误
- android支持的语言
- 实施工程师面试题(答案)
- android adb调试技巧
热门文章
- easyUI下datagrid嵌套显示
- 9.Python基础 面向对象的进一步拓展
- 诗歌rails 之with_options
- 【python数据挖掘课程】十一.Pandas、Matplotlib结合SQL语句可视化分析
- 【数据结构与算法】之深入解析“二叉树的最小深度”的求解思路与算法示例
- 【数据结构与算法】之深入解析“字符串相乘”的求解思路与算法示例
- 【网络通信与信息安全】之深入解析TCP的“拥塞控制”原理
- iOS之CALayer的CAEmitterLayer实现“红包雨”效果
- python获取计算机IP、mac地址、计算机名
- 2015年第六届蓝桥杯C/C++ A组国赛 —— 第三题:显示二叉树