题目描述

小a虽然是一名理科生,但他常常称自己是一名真正的文科生。不知为何,他对于背诵总有一种莫名其妙的热爱,这也促使他走向了以记忆量大而闻名的生物竞赛。然而,他很快发现这并不能满足他热爱背诵的心,但是作为一名强大的OIER,他找到了这么一个方法——背诵基因序列。然而这实在是太困难了,小啊感觉有些招架不住。不过他发现,如果他能事先知道这个序列里有多少对互不相交的回文串,他或许可以找到记忆的妙法。为了进一步验证这个想法,小a决定选取一个由小写字母构成的字符串SS来实验。由于互不相关的回文串实在过多,他很快就数晕了。不过他相信,在你的面前这个问题不过是小菜一碟。

(1)对于字符串SS,设其长度为Len,那么下文用Si表示SS中第i个字符(1<=i<=Len)。

(2)S[i,j]表示SS的一个子串,S[i,j]="SiSi+1Si+2...Sj-2Sj-1Sj",比如当SS为"abcgfd"时,S[2,5]="bcgf",S[1,5]="abcgf"。

(3)当一个串被称为一个回文串当且仅当将这个串反写后与原串相同,如“abcba”。

(4)考虑一个四元组(l,r,L,R),当S[l,r]和S[L,R]均为回文串时,且满足1<=l<=r<=L<=R<=Len时,我们称S[l,r]和S[L,R]为一对互不相交的回文串。即本题所求,也即为这种四元组的个数。两个四元组相同当且仅当对应的l,r,L,R都相同。

输入输出格式

输入格式:

输入仅一行,为字符串SS,保证全部由小写字母构成,由换行符标志结束。

50%的数据满足SS的长度不超过200;

100%的数据满足SS的长度不超过2000。

输出格式:

仅一行,为一个整数,表示互不相关的回文串的对数。

输入输出样例

输入样例#1: 复制

aaa

输出样例#1: 复制

5

说明

【样例数据说明】

SS="aaa",SS的任意一个字符串均为回文串,其中总计有5对互不相关的回文串:

(1,1,2,2),(1,1,2,3),(1,1,3,3),(1,2,3,3),(2,2,3,3)。


题解

在这里我们对回文树引入一个新的标记,dep

它表示的是当前这个节点为回文串时,以它结尾的串中包含的回文串的数量

好,那么接下来的意思就很简单了。

我们只需要依次递推过去,先更新出原本顺序上每一位的回文串的数量,再更新出倒序上每一位的回文串的数量(其实倒序就是求尾部的回文串数量)。

这样我们每更新一位,就加上之前每一位的回文串的数量。再乘以下一位的按倒序处理出来的回文串的数量就ok了。


代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int tot;
ll ans,p1[20001],p2[20001];
struct node{
int fail,ch[26],len,cnt,dep;
}t[200001];
char s[200001]; int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
} void solve1()
{
int len=strlen(s+1),k=0;s[0]='#';
t[0].fail=t[1].fail=1;t[1].len=-1;tot=1;
for(int i=1;i<=len;i++)
{
while(s[i-t[k].len-1]!=s[i])k=t[k].fail;
if(!t[k].ch[s[i]-'a']){
t[++tot].len=t[k].len+2;
int j=t[k].fail;
while(s[i-t[j].len-1]!=s[i])j=t[j].fail;
t[tot].fail=t[j].ch[s[i]-'a'];
t[k].ch[s[i]-'a']=tot;
t[tot].dep=t[t[tot].fail].dep+1;
}
k=t[k].ch[s[i]-'a'];
p1[i]=t[k].dep;
t[k].cnt++;
}
} void solve2()
{
int len=strlen(s+1),k=0;s[0]='#';
t[0].fail=t[1].fail=1;t[1].len=-1;tot=1;
for(int i=1;i<=len;i++)
{
while(s[i-t[k].len-1]!=s[i])k=t[k].fail;
if(!t[k].ch[s[i]-'a']){
t[++tot].len=t[k].len+2;
int j=t[k].fail;
while(s[i-t[j].len-1]!=s[i])j=t[j].fail;
t[tot].fail=t[j].ch[s[i]-'a'];
t[k].ch[s[i]-'a']=tot;
t[tot].dep=t[t[tot].fail].dep+1;
}
k=t[k].ch[s[i]-'a'];
t[k].cnt++;
p2[len-i+1]=t[k].dep;
}
} int main()
{
scanf("%s",s+1);
int len=strlen(s+1);
solve1();
reverse(s+1,s+len+1);
memset(t,0,sizeof(t));
solve2();
for(int i=1;i<=len;i++)p1[i]+=p1[i-1];
for(int i=1;i<=len;i++)ans+=p1[i]*p2[i+1];
printf("%lld",ans);
return 0;
}

P1872 回文串计数(回文树)的更多相关文章

  1. 【BZOJ2565】最长双回文串(回文树)

    [BZOJ2565]最长双回文串(回文树) 题面 BZOJ 题解 枚举断点\(i\) 显然的,我们要求的就是以\(i\)结尾的最长回文后缀的长度 再加上以\(i+1\)开头的最长回文前缀的长度 至于最 ...

  2. 【NOIP模拟赛】【乱搞AC】【奇技淫巧】【乘法原理】回文串计数

    回文串计数 (calc.pas/calc.c/calc.cpp) [题目描述] 虽然是一名理科生,Mcx常常声称自己是一名真正的文科生.不知为何,他对于背诵总有一种莫名的热爱,这也促使他走向了以记忆量 ...

  3. BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)

    BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...

  4. BZOJ 3676 [Apio2014]回文串(回文树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题目大意] 考虑一个只包含小写拉丁字母的字符串s. 我们定义s的一个子串t的& ...

  5. bzoj 2565: 最长双回文串【manacher+线段树】

    因为我很愚蠢所以用了很愚蠢的O(nlogn)的manacher+线段树做法 就是开两个线段树mn和mx分别表示左端点在i的最长回文子串和右端点在i的最长回文子串 用manacher求出每个点的最长回文 ...

  6. P3649 [APIO2014]回文串(回文树)

    题目描述 给你一个由小写拉丁字母组成的字符串 ss .我们定义 ss 的一个子串的存在值为这个子串在 ss 中出现的次数乘以这个子串的长度. 对于给你的这个字符串 ss ,求所有回文子串中的最大存在值 ...

  7. BZOJ 3676 回文串(回文树)题解

    题意: 一个回文的价值为长度 * 出现次数,问一个串中的子串的最大回文价值 思路: 回文树模板题,跑PAM,然后计算所有节点出现次数. 参考: 回文串问题的克星--Palindrome Tree(回文 ...

  8. Misha and Palindrome Degree CodeForces - 501E (回文串计数)

    大意: 给定字符串, 求多少个区间重排后能使原串为回文串. 先特判掉特殊情况, 对于两侧已经相等的位置之间可以任意组合, 并且区间两端点至少有一个在两侧相等的位置处, 对左右两种情况分别求出即可. # ...

  9. 3676: [Apio2014]回文串 求回文串长度与出现次数的最大值

    「BZOJ3676」[Apio2014] 回文串   Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所 ...

随机推荐

  1. System.IO.FileLoadException异常

    未能加载文件或程序集“NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4”或它的某一个依赖 ...

  2. Analysis of the Facebook.app for iOS

    Analysis of the Facebook.app for iOS Posted Oct 18, 2016 Did you ever wonder why the Facebook.app fo ...

  3. asp.net HTTP请求过程

    http://blog.csdn.net/zxxSsdsd/article/details/51909860

  4. Ubuntu 14.04下从源码安装qt4.x

    转自:http://www.cnblogs.com/crazywangzx/p/3505293.html 1.到官网http://qt-project.org/downloads或者ftp://ftp ...

  5. FCC高级编程篇之Symmetric Difference

    Symmetric Difference Create a function that takes two or more arrays and returns an array of the sym ...

  6. eclipse历史版本下载地址

    http://wiki.eclipse.org/Older_Versions_Of_Eclipse

  7. django 获得请求头

    django 获得到的请求头封装在 request 的 META 中,为一个 dict 以下选自官方文档: https://docs.djangoproject.com/zh-hans/2.0/ref ...

  8. Promise语法

    转自:廖雪峰的官方网站 在JavaScript的世界中,所有代码都是单线程执行的. 由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行.异步执行可以用回调函数实现: ...

  9. java实现websocket 终极指南

    大概思路:  首先用户登陆  获取用户信息存储到httpsession中,然后客户端链接服务端websocket,首先HandshakeInterceptor这个拦截器会拦截请求 调用 beforeH ...

  10. docker环境下mysql参数修改

    原文:docker环境下mysql参数修改 需要修改log_bin为on,看了好几个博客说都需要删掉容器重新生成,然而并非如此, 我们可以用docker cp 命令将docker的文件"下载 ...