Palindromeness

Let us define the palindromeness of a string in the following way:

  • If the string is not a palindrome, its' palindromeness is zero.
  • The palindromeness of an one-letter string is 1.
  • The palindromness of a string S of the length greater than one is 1 + "palindromeness of the string that is formed by the first [|S|/2] symbols of S".

You are given a string S. Find the sum of the palindromenesses of all the non empty substrings of S (i.e. S[i..j], where i <= j). In other words, you have to calculate the sum of palindromenesses of N * (N + 1) / 2 substrings of S, where N is the length of S.

  • 1 ≤ |S| ≤ 105。

题解

翁文涛《回文树及其应用》。

\(len_i=1\) 时特殊处理 \(half_i=even\)。

CO int N=100000+10;

namespace PAM{
int str[N],n;
int last,tot;
int ch[N][26],fa[N],len[N];
int half[N],val[N],siz[N]; void init(){
memset(str,-1,sizeof str),n=0;
last=tot=1;
memset(ch,0,sizeof ch);
fa[0]=fa[1]=1,len[0]=0,len[1]=-1;
memset(siz,0,sizeof siz);
}
int get_fail(int x){
while(str[n-len[x]-1]!=str[n]) x=fa[x];
return x;
}
void extend(int c){
int p=get_fail(last);
if(!ch[p][c]){
int cur=++tot;
len[cur]=len[p]+2;
fa[cur]=ch[get_fail(fa[p])][c];
ch[p][c]=cur;
if(len[cur]==1) half[cur]=0;
else{
int q=half[p];
while(str[n-len[q]-1]!=str[n] or
2*(len[q]+2)>len[cur]) q=fa[q];
half[cur]=ch[q][c];
}
val[cur]=1+(len[cur]/2==len[half[cur]]?val[half[cur]]:0);
}
last=ch[p][c];
++siz[last];
}
LL main(){
for(int i=tot;i>=2;--i) siz[fa[i]]+=siz[i];
LL ans=0;
for(int i=tot;i>=2;--i) ans+=(LL)siz[i]*val[i];
return ans;
}
} char str[N]; void real_main(){
scanf("%s",str+1);
int n=strlen(str+1);
PAM::init();
for(int i=1;i<=n;++i){
PAM::str[++PAM::n]=str[i]-'a';
PAM::extend(str[i]-'a');
}
printf("%lld\n",PAM::main());
}
int main(){
for(int T=read<int>();T--;) real_main();
return 0;
}

双倍回文

如果 s 能够写成 wwRwwR 的形式,则称 s 是双倍回文。

s 的长度是 4 的倍数,前后两半都是相同的回文。

对于给定的字符串,计算它的最长双倍回文串的长度。

N<=500000

yyb的题解

发现这个长度为自身一半的的回文串是可以方便地转移的。

对于每个节点,我们维护一个half来表示长度最长的、不超过它长度一半的那个祖先节点

这样子只需要判断一下当前点的half长度是否是一半,并且当前串的长度是四的倍数就好了

找 half 就用 p 的 half 来跳就行了。

co int N=500000+10;
char s[N];
int last=1,tot=1;
int ch[N][26],fa[N]={1,1},len[N]={0,-1},half[N]; int get_fa(int x,int i){
while(s[i-len[x]-1]!=s[i]) x=fa[x];
return x;
}
void extend(int i){
int p=get_fa(last,i);
int x=ch[p][s[i]-'a'];
if(!x){
x=++tot;
fa[x]=ch[get_fa(fa[p],i)][s[i]-'a'];
len[x]=len[p]+2;
ch[p][s[i]-'a']=x;
if(len[x]==1) half[x]=0;
else{
int q=half[p];
while(s[i-len[q]-1]!=s[i]||(len[q]+2)<<1>len[x]) q=fa[q];
half[x]=ch[q][s[i]-'a'];
}
}
last=x;
}
int main(){
int n=read<int>();
scanf("%s",s+1);
for(int i=1;i<=n;++i) extend(i);
int ans=0;
for(int i=1;i<=tot;++i)
if(len[half[i]]<<1==len[i]&&len[i]%4==0)
ans=max(ans,len[i]);
printf("%d\n",ans);
return 0;
}

Codechef Palindromeness 和 SHOI2011 双倍回文的更多相关文章

  1. BZOJ2342: [Shoi2011]双倍回文

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 923  Solved: 317[Submit][Status ...

  2. 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...

  3. BZOJ 2342: [Shoi2011]双倍回文 马拉车算法/并查集

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1123  Solved: 408 题目连接 http://w ...

  4. [SHOI2011]双倍回文 manacher

    题面: 洛谷:[SHOI2011]双倍回文‘ 题解: 首先有一个性质,本质不同的回文串最多O(n)个. 所以我们可以对于每个i,求出以这个i为结尾的最长回文串,然后以此作为长串,并判断把这个长串从中间 ...

  5. bzoj 2342: [Shoi2011]双倍回文 -- manacher

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符 ...

  6. BZOJ2342 Shoi2011 双倍回文 【Manacher】

    BZOJ2342 Shoi2011 双倍回文 Description Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输 ...

  7. Manacher || BZOJ 2342: [Shoi2011]双倍回文 || Luogu P4287 [SHOI2011]双倍回文

    题面:[SHOI2011]双倍回文 题解:具体实现时,就是在更新mr时维护前半段是回文串的最长回文串就好了 正确性的话,因为到i时如果i+RL[i]-1<=mr,那么答案肯定在i之前就维护过了: ...

  8. [SHOI2011]双倍回文

    Description   Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输出文件只有一行,即:输入数据中字符串的最长 ...

  9. BZOJ2342[Shoi2011]双倍回文——回文自动机

    题目描述 输入 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. 输出 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文 ...

随机推荐

  1. 小程序报错 “渲染层错误” Expect END descriptor with depth 0 but get another

    项目中有几个页面在控制台出现这个“渲染层错误”,虽然不影响业务操作,怕存在潜在风险,今天抽时间找了下原因,解决这个问题. 控制台报错日志如下: (中国标准时间) 渲染层错误 Error: Expect ...

  2. 手机上的unity路径

    转载自:https://www.xuanyusong.com/archives/2656 Application.dataPath路径在PC上无论是Editor还是运行时毫无压力非常万能,但是在手机上 ...

  3. 深入理解AQS

    前记 在看JUC中并发相关的源码时经常看到AQS的身影,这到底是个什么鬼?必须要一探究竟. 一. AQS背景了解 JUC包中的锁,包括: Lock接口,ReadWriteLock接口,LockSupp ...

  4. SQL系列(十二)—— insert update delete

    前言 这个系列的前面都一直在介绍查询select.但是SQL中十分广泛,按对数据的不同处理可以分为: DML:全称Data Manipulation Language,从名字上可以看出,DML是对数据 ...

  5. golang---命令源码文件与命令行参数

    命令源码文件是程序的运行入口,是每个可独立运行的程序必须拥有的. import "flag"  flag包实现了命令行参数的解析.每个参数认为一条记录,根据实际进行定义,到一个se ...

  6. Scala 系列(十一)—— 模式匹配

    一.模式匹配 Scala 支持模式匹配机制,可以代替 swith 语句.执行类型检查.以及支持析构表达式等. 1.1 更好的swith Scala 不支持 swith,可以使用模式匹配 match.. ...

  7. Linux学习笔记之grep命令和使用正则表达式

    0x00 正则表达式概述 正则表达式是描述一些字符串的模式,是由一些元字符和字符组成的字符串,而这些元字符是一些表示特殊意义的字符,即被正则表达式引擎表达的字符表示与其本意不同的一些字符. 0x01  ...

  8. 示例:在Nuget发布自己的包的步骤

    原文:示例:在Nuget发布自己的包的步骤 一.目的:很多时候都在用第三方的Nuget包,现成的轮子可以减少很多工作量,同时我们也可以造轮子供自己和其他人使用,本示例主要演示如何发布dll到Nuget ...

  9. SQL 2008R2问题:用户、组或角色'XXX'在当前数据库中已存在?

    为一个数据库添加一个用户或者映射数据库时,提示以下错误信息: 用户.组或角色 '*****' 在当前数据库中已存在. (Microsoft SQLServer, 错误 : 15023) 问题原因:在还 ...

  10. Ubuntu中的两套网络连接管理方式

     版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/haifeng_gu/article/details/78286895 Linux里面有两套管理网络 ...