考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串。

所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串。

最后拓扑排序递推就行了。。。

这道题丧心病狂卡哈希。。。。wa了一屏。。。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#define bas 131
#define bs 31
#define p 1000000007
#define p2 986598521
#define ll long long
#define N 1200005
using namespace std;
char c[N],s[N*];
int hui[N],n;
ll hash[N],pw[N],hash2[N],pw2[N];
int head[],nxt[N],tot,len[N],size[N],zhi[N];
ll key[N],key2[N],nx[N],nx2[N];
void insert(ll x,ll xx,int l,ll z,int ss,ll ww)
{
int y=x%;
tot++;nxt[tot]=head[y];head[y]=++tot;len[tot]=l;key[tot]=x;nx[tot]=z;zhi[tot]=ss;key2[tot]=xx;nx2[tot]=ww;
return ;
}
int find(ll x,ll xx)
{
int y=x%;
for(int i=head[y];i;i=nxt[i])
{
if(key[i]==x&&key2[i]==xx)return i;
}
return ;
}
int head2[N],ver2[N],nxt2[N],tot2;
void add2(int x,int y)
{
tot2++;nxt2[tot2]=head2[x];head2[x]=tot2;ver2[tot2]=y;return ;
}
void manachar()
{
int mx=,id=;
for(int i=;i<=n;i++)
{
if(i>mx)
{
hui[i]=;
mx=i;id=i;
}
else
{
hui[i]=min(hui[id-(i-id)],mx-i+);
}
int l=i-hui[i],r=i+hui[i];
while(l!=&&r!=n+&&s[l]==s[r])
{
hui[i]++;
mx=i+hui[i]-;
id=i;
l--;r++;
}
int tmp=hui[i];
if(s[i+hui[i]-]=='#')tmp--;
if(tmp==)continue;
int pos2=tmp+i-,pos1=i-tmp+;
int lenn=(pos2-pos1)/+;
ll haha,haha2;
ll ha=(hash[pos2/]-(hash[pos1/-]*pw[lenn])%p+p)%p;
ll ha2=(hash2[pos2/]-(hash2[pos1/-]*pw2[lenn])%p2+p2)%p2;
if(pos2==pos1||pos2==pos1+)haha=,haha2=;
else haha=(hash[pos2/-]-(hash[pos1/]*pw[lenn-])%p+p)%p,haha2=(hash2[pos2/-]-(hash2[pos1/]*pw2[lenn-])%p2+p2)%p2;
int k=find(ha,ha2);
if(!k)insert(ha,ha2,lenn,haha,pos2/,haha2),size[tot]++;
else size[k]++;
}
}
queue<int>qu;
int ru[N];
ll ans;
void tupu()
{
for(int i=;i<=tot;i++)if(!ru[i])qu.push(i);
while(!qu.empty())
{
int tmp=qu.front();qu.pop();
ans=max(ans,(ll)size[tmp]*len[tmp]);
for(int i=head2[tmp];i;i=nxt2[i])
{
ru[ver2[i]]--;
size[ver2[i]]+=size[tmp];
if(!ru[ver2[i]])qu.push(ver2[i]);
}
}
}
int main()
{
scanf("%s",c+);
n=strlen(c+);
pw[]=;pw2[]=;
for(int i=;i<=n;i++)pw[i]=(pw[i-]*bas)%p;
for(int i=;i<=n;i++)pw2[i]=(pw2[i-]*bs)%p2;
for(int i=;i<=n;i++)hash[i]=(hash[i-]*bas+c[i]-'a'+)%p;
for(int i=;i<=n;i++)hash2[i]=(hash2[i-]*bs+c[i]-'a'+)%p2;
for(int i=;i<=n*+;i++)
{
if(i&)s[i]='#';
else s[i]=c[i/];
}
n=n*+;
manachar();
for(int i=;i<=tot;i++)
{
if(nx[i]==)continue;
int tmp=find(nx[i],nx2[i]);
if(tmp!=)add2(i,tmp),ru[tmp]++;
else
{
ll now,now2;
if(len[i]<=)now=,now2=;
else
{
now=(hash[zhi[i]-]-(hash[zhi[i]-len[i]+]*pw[len[i]-])%p+p)%p;
now2=(hash2[zhi[i]-]-(hash2[zhi[i]-len[i]+]*pw2[len[i]-])%p2+p2)%p2;
}
insert(nx[i],nx2[i],len[i]-,now,zhi[i]-,now2);
add2(i,tot);ru[tot]++;
}
}
tupu();
printf("%lld\n",ans);
return ;
}
 

bzoj 3676 回文串 manachar+hash的更多相关文章

  1. 回文树(回文自动机) - BZOJ 3676 回文串

    BZOJ 3676 回文串 Problem's Link: http://www.lydsy.com/JudgeOnline/problem.php?id=3676 Mean: 略 analyse: ...

  2. BZOJ 3676 回文串

    Description 考虑一个只包含小写拉丁字母的字符串\(s\).我们定义\(s\)的一个子串\(t\)的"出现值"为\(t\)在\(s\)中的出现次数乘以\(t\)的长度.请 ...

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

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

  4. BZOJ - 3676 回文串 (回文树)

    https://vjudge.net/problem/HYSBZ-3676 题意 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s ...

  5. HYSBZ 3676 回文串 (回文树)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1680  Solved: 707 [Submit][Stat ...

  6. [CSP-S模拟测试]:回文串(hash+二分)

    题目描述 $ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳.有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空 ...

  7. BZOJ 2342 回文串-Manacher

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2342 思路:先跑一遍Manacher求出p[i]为每个位置为中心的回文半径,因为双倍回文串 ...

  8. BZOJ 2565 回文串-Manacher

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2565 题意:中文题 思路:定义L[i],R[i].表示以i为左端点/右端点时,最长回文串长 ...

  9. POWEROJ 2610 判断回文串 【HASH】

    题目链接[https://www.oj.swust.edu.cn/problem/show/2610] 题意:给你一个字符串,让你判断这个字符串是不是回文串,字符串的长度是1<len<1e ...

随机推荐

  1. Java--String 和StringBuilder、StringBuffer 的区别?

    1.String是只读字符串,引用的字符串内容是无法改变的. 2.StringBuffer和StringBuilder的字符串对象可以直接进行修改. 3.StringBuilder没有被synchro ...

  2. java 开发业务逻辑的思考(1)- 通知短信发送

    坚持每天写一个总结的博客,今天又是一个新的开始! 今天我要说的是一个关于发送短信通知发送的问题.具体的业务流程是这样的,现在需要对用户的一个提现的申请进行审核,审核的内部需要控制很多的业务, 1.检查 ...

  3. php注释规范

    注释在写代码的过程中非常重要,好的注释能让你的代码读起来更轻松,在写代码的时候一定要注意注释的规范.(李昌辉) php里面常见的几种注释方式: 1.文件头的注释,介绍文件名,功能以及作者版本号等信息 ...

  4. Android Weekly Notes Issue #219

    Android Weekly Issue #219 August 21st, 2016 Android Weekly Issue #219 ARTICLES & TUTORIALS Andro ...

  5. android基于口令加密快速搞懂(一)

    import java.util.Random; import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypt ...

  6. ios动态创建类Class

    [Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...

  7. HDFS的架构

    主从结构 主节点,只有一个: namenode 从节点,有很多个: datanodes 在版本1中,主节点只有一个,在 版本2中主节点有两个. namenode 负责(管理): 接收用户操作请求 维护 ...

  8. Java使用POS打印机(无驱)

    使用原因:应项目要求,需要使用打印机,但是如果使用Windows驱动来实现打印,在某些条件下会发生网络堵塞等,而且没有提示,所以为了确保信息的完整,避免数据丢失.我们使用无驱打印(直接写端口的方法), ...

  9. Js IP转数字

    <script type="text/javascript"> function d2h(d) { return d.toString(16) } function h ...

  10. 重邮二进制日天群-pwn1

    给学弟们练手的题目,做的过程中接触一些基本概念 #include <stdio.h> #include <unistd.h> int main() { ]; welcome() ...