P1872 回文串计数(回文树)
题目描述
小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 回文串计数(回文树)的更多相关文章
- 【BZOJ2565】最长双回文串(回文树)
[BZOJ2565]最长双回文串(回文树) 题面 BZOJ 题解 枚举断点\(i\) 显然的,我们要求的就是以\(i\)结尾的最长回文后缀的长度 再加上以\(i+1\)开头的最长回文前缀的长度 至于最 ...
- 【NOIP模拟赛】【乱搞AC】【奇技淫巧】【乘法原理】回文串计数
回文串计数 (calc.pas/calc.c/calc.cpp) [题目描述] 虽然是一名理科生,Mcx常常声称自己是一名真正的文科生.不知为何,他对于背诵总有一种莫名的热爱,这也促使他走向了以记忆量 ...
- BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)
BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...
- BZOJ 3676 [Apio2014]回文串(回文树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题目大意] 考虑一个只包含小写拉丁字母的字符串s. 我们定义s的一个子串t的& ...
- bzoj 2565: 最长双回文串【manacher+线段树】
因为我很愚蠢所以用了很愚蠢的O(nlogn)的manacher+线段树做法 就是开两个线段树mn和mx分别表示左端点在i的最长回文子串和右端点在i的最长回文子串 用manacher求出每个点的最长回文 ...
- P3649 [APIO2014]回文串(回文树)
题目描述 给你一个由小写拉丁字母组成的字符串 ss .我们定义 ss 的一个子串的存在值为这个子串在 ss 中出现的次数乘以这个子串的长度. 对于给你的这个字符串 ss ,求所有回文子串中的最大存在值 ...
- BZOJ 3676 回文串(回文树)题解
题意: 一个回文的价值为长度 * 出现次数,问一个串中的子串的最大回文价值 思路: 回文树模板题,跑PAM,然后计算所有节点出现次数. 参考: 回文串问题的克星--Palindrome Tree(回文 ...
- Misha and Palindrome Degree CodeForces - 501E (回文串计数)
大意: 给定字符串, 求多少个区间重排后能使原串为回文串. 先特判掉特殊情况, 对于两侧已经相等的位置之间可以任意组合, 并且区间两端点至少有一个在两侧相等的位置处, 对左右两种情况分别求出即可. # ...
- 3676: [Apio2014]回文串 求回文串长度与出现次数的最大值
「BZOJ3676」[Apio2014] 回文串 Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所 ...
随机推荐
- 【实战经验】64位Win7安装+32位Oracle + PL/SQL 解决方法
软件环境:64位win7.32位Oracle 10g. PL/SQL 9.0.4.1644 前言:以前开发用的都是32位系统,突然换到64位上,安装环境真的有点麻烦了,尤其对于PL/SQL只支持32位 ...
- go语言简单的执行shell命令
package main import( "fmt" "os/exec" "os" "string ...
- Ubuntu16.04 lnmp 环境搭建
Ubuntu16.04 lnmp 环境搭建 nginx 安装 sudo apt-add-repository ppa:nginx/stablesudo apt-add-repository ppa:o ...
- thymeleaf 常用标签
1.th:field th:field="*{user.sex}" 此标签会自动填充数据,比如用户的性别 user.sex 如果不为空,则会自动勾选上 2.th:each=&qu ...
- centos6.5安装配置nginx+php+mysql+httpsqs+ttserver+redis
一.准备 1.nginx, http://nginx.org/download/nginx-1.5.12.tar.gz 2.pcre, ftp://ftp.csx.cam.ac.uk/pub/soft ...
- GBK编码具体解析(附GBK码位分布图)
1.GBK码位分布图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA= ...
- SVN配置以及自己主动部署到apache虚拟文件夹
SVN配置以及自己主动部署到apache虚拟文件夹 一.VisualSVN server 服务端和TortoiseSVNclient下载 VisualSVN下载:http://subversion.a ...
- Codeforces Round #271 (Div. 2) 解题报告
题目地址:http://codeforces.com/contest/474 A题:Keyboard 模拟水题. 代码例如以下: #include <iostream> #include ...
- [Perl系列—] 2. Perl 中的引用使用方法
Perl 中的引用,为什么要使用引用? 对于熟悉C语言的开发人员来说, 指针这个概念一定不陌生. Perl 的引用就是指针,能够指向变量.数组.哈希表甚至子程序. Perl5中的两种Perl引用类型为 ...
- 设置Webdriver启动chrome为默认用户的配置信息
Webdriver 启动Chrome浏览器时,默认是打开一个新用户,而非默认用户.即新用户没有我们安装扩展程序.但在实际应用中,我们会须要 默认用户安装的一些扩展程序,比方对于某些js或者css样式. ...