题目链接

题意

给一个字符串,求字符串子串的最大集合,集合中字符串互不相等,相等的定义为: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 (后缀自动机+回文树)相关推荐

  1. 【2019牛客暑期多校训练营(第二场)- E】MAZE(线段树优化dp,dp转矩阵乘法,线段树维护矩阵乘法)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/E?&headNav=acm 来源:牛客网 Given a maze with N rows an ...

  2. 2019牛客暑期多校训练营(第九场)H Cutting Bamboos(主席树+二分)

    链接:https://ac.nowcoder.com/acm/contest/889/H 来源:牛客网 题目描述 There are n bamboos arranged in a line. The ...

  3. 【2019牛客暑期多校训练营(第二场) - H】Second Large Rectangle(单调栈,全1子矩阵变形)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/H 来源:牛客网 题目描述 Given a N×MN \times MN×M binary matrix. ...

  4. 2019牛客暑期多校训练营(第一场)E-ABBA(dp)

    链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...

  5. 2019牛客暑期多校训练营(第一场)

    传送门 参考资料: [1]:官方题解(提取码:t050 ) [2]:标程(提取码:rvxr ) [3]:牛客题解汇总 A.Equivalent Prefixes(单调栈) •题意 定义两个数组 u,v ...

  6. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  7. 【2019牛客暑期多校训练营(第二场)- F】Partition problem(dfs,均摊时间优化)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/F 来源:牛客网 Given 2N people, you need to assign each of ...

  8. 【2019牛客暑期多校训练营(第二场) - D】Kth Minimum Clique(bfs,tricks)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/D 来源:牛客网 Given a vertex-weighted graph with N vertice ...

  9. 【2019牛客暑期多校训练营(第一场) - A】Equivalent Prefixes(单调栈,tricks)

    题干: 链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Two arrays u and v each with m distinct elem ...

  10. 【2019牛客暑期多校训练营(第一场) - H】XOR(线性基,期望的线性性)

    题干: 链接:https://ac.nowcoder.com/acm/contest/881/H 来源:牛客网 Bobo has a set A of n integers a1,a2,-,ana1, ...

最新文章

  1. session过期重新登陆_深入分析Session和Cookie-前端面试题
  2. linux学习-用户的特殊 shell 与 PAM 模块
  3. 台湾印象之三:吃与喝
  4. python中decode的用法_python中list怎么使用decode方法设置编码
  5. 深入理解Mysql - 事务与锁原理
  6. python在原有的字符串的基础上追加列表构成的字符串,并保持格式一致
  7. 【Elasticsearch】Elasticsearch Span Query跨度查询
  8. 【报告分享】中国营销数字化行业趋势报告:全渠道时代,品牌商如何抓住消费者?(附下载链接)...
  9. oracle删除数据释放表空间流程
  10. c语言的课本答案,c语言课本试题答案
  11. Convirt管理机Socat驻留进程故障处理
  12. tensorflow2.0内存溢出解决办法
  13. hi3559AV100上交叉编译faiss(facebook research)
  14. WDSR:Wide Activation for Efficient and Accurate Image Super-Resolution
  15. 几本开关电源书籍 pdf格式 (来源中国电子开发网)
  16. 80后年轻老板创业心经
  17. iTop4412---linux 3.0.15内核编译错误
  18. android支持的语言
  19. 实施工程师面试题(答案)
  20. android adb调试技巧

热门文章

  1. easyUI下datagrid嵌套显示
  2. 9.Python基础 面向对象的进一步拓展
  3. 诗歌rails 之with_options
  4. 【python数据挖掘课程】十一.Pandas、Matplotlib结合SQL语句可视化分析
  5. 【数据结构与算法】之深入解析“二叉树的最小深度”的求解思路与算法示例
  6. 【数据结构与算法】之深入解析“字符串相乘”的求解思路与算法示例
  7. 【网络通信与信息安全】之深入解析TCP的“拥塞控制”原理
  8. iOS之CALayer的CAEmitterLayer实现“红包雨”效果
  9. python获取计算机IP、mac地址、计算机名
  10. 2015年第六届蓝桥杯C/C++ A组国赛 —— 第三题:显示二叉树