bzoj 3676 回文串 manachar+hash
考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串。
所以我们可以用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的更多相关文章
- 回文树(回文自动机) - BZOJ 3676 回文串
BZOJ 3676 回文串 Problem's Link: http://www.lydsy.com/JudgeOnline/problem.php?id=3676 Mean: 略 analyse: ...
- BZOJ 3676 回文串
Description 考虑一个只包含小写拉丁字母的字符串\(s\).我们定义\(s\)的一个子串\(t\)的"出现值"为\(t\)在\(s\)中的出现次数乘以\(t\)的长度.请 ...
- BZOJ 3676 回文串(回文树)题解
题意: 一个回文的价值为长度 * 出现次数,问一个串中的子串的最大回文价值 思路: 回文树模板题,跑PAM,然后计算所有节点出现次数. 参考: 回文串问题的克星--Palindrome Tree(回文 ...
- BZOJ - 3676 回文串 (回文树)
https://vjudge.net/problem/HYSBZ-3676 题意 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s ...
- HYSBZ 3676 回文串 (回文树)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 1680 Solved: 707 [Submit][Stat ...
- [CSP-S模拟测试]:回文串(hash+二分)
题目描述 $ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳.有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空 ...
- BZOJ 2342 回文串-Manacher
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2342 思路:先跑一遍Manacher求出p[i]为每个位置为中心的回文半径,因为双倍回文串 ...
- BZOJ 2565 回文串-Manacher
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2565 题意:中文题 思路:定义L[i],R[i].表示以i为左端点/右端点时,最长回文串长 ...
- POWEROJ 2610 判断回文串 【HASH】
题目链接[https://www.oj.swust.edu.cn/problem/show/2610] 题意:给你一个字符串,让你判断这个字符串是不是回文串,字符串的长度是1<len<1e ...
随机推荐
- Java三大框架之——Hibernate中的三种数据持久状态和缓存机制
Hibernate中的三种状态 瞬时状态:刚创建的对象还没有被Session持久化.缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有OID. 持久状态:对象经过 ...
- 设计模式-策略模式(Strategy Model)
1.概述 在开发过程中常常会遇到类似问题,实现一个功能的时候往往有多种算法/方法(策略),我们可以根据环境的不同来使用不同的算法或策略来实现这一功能. 如在人物比较排序的实现中,我们有 ...
- 微信小程序注册
小程序是一种新的开放能力,可以在微信内被便捷地获取和传播,同时具有出色的使用体验.开发者可以根据平台提供的能力,快速地开发一个小程序. 开放内容包括: 1.开放注册范围:企业.政府.媒体.其他组织: ...
- BFC深入理解
BFC 在上一篇文章中,清除浮动方法解析,我们谈及了一些使用css属性解决浮动带来的影响.但是在解决浮动带来的影响的方法中,如果细心思考,会产生如下疑问: 为什么overflow可以清除浮动带来的影响 ...
- 大数据下BI产品如何发挥最大价值
看到这个题目,你是否总感觉云里雾里?你是否真正懂什么叫“大数据”?商业智能BI和大数据又有着什么千丝万缕的联系?为什么说商业智能BI能在大数据中发挥价值? 大数据,指的是所涉及的数据资料量规模巨大到无 ...
- UITableView点击每个Cell,Cell的子内容的收放
关于点击TableviewCell的子内容收放问题,拿到它的第一个思路就是, 方法一: 运用UITableview本身的代理来处理相应的展开收起: 1.代理:- (void)tableView:(UI ...
- 最快让你上手ReactiveCocoa之基础篇
前言 很多blog都说ReactiveCocoa好用,然后各种秀自己如何灵活运用ReactiveCocoa,但是感觉真正缺少的是一篇如何学习ReactiveCocoa的文章,这里介绍一下. 1.Rea ...
- 强大的flash头像上传插件(支持旋转、拖拽、剪裁、生成缩略图等)
今天介绍的这款flash上传头像功能非常强大,支持php,asp,jsp,asp.net 调用 头像剪裁,预览组件插件. 本组件需要安装Flash Player后才可使用,请从http://dl.pc ...
- ps如何裁剪掉图片的不规则区域
按P,鼠标变成钢笔工具,点选住待清除区域,如下: 按ctrl+enter, 将点线变成选中区域: 按delete删除: ctrl+D取消选中区域 完成!
- SQL优化技术分析-4:其他
ORACLE的提示功能是比较强的功能,也是比较复杂的应用,并且提示只是给ORACLE执行的一个建议,有时如果 出于成本方面的考虑ORACLE也可能不会按提示进行.根据实践应用,一般不建议开发人员应用O ...