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 ...
随机推荐
- CSS代码规范
空格 选择器 与 { 之间必须包含空格. 列表型属性值 书写在单行时,, 后必须跟一个空格. 属性名 与之后的 : 之间不允许包含空格, : 与 属性值 之间必须包含空格. margin: 0; .+ ...
- 《C#微信开发系列(Top)-微信开发完整学习路线》
年前就答应要将微信开发的学习路线整理给到大家,但是因为年后回来这段时间学校还有公司那边有很多事情需要兼顾,所以没能及时更新文章.今天特地花时间整理了下,话不多说,上图,希望对大家的学习有所帮助哈. 如 ...
- px-rem 一个将px转换为rem的工具
将px转换为rem的工具,github地址:https://github.com/finance-sh/px-rem 怎样转换静态文件 安装: npm install px-rem -g 然后跑下命令 ...
- 纯Swift编写的仿“随遇”应用源码
纯Swift编写的仿“随遇”App概述 此项目是为了巩固Swift掌握而编写的,素材均来自“随遇”官方App 用Storyboard+Xib+Autolayout的方式来实现UI部分 由于项目不复杂, ...
- ORACLE RETURNING 用法总结
ORACLE RETURNING 用法总结 场景 在存储过程.PL/SQL块里需要返回INSERT.DELETE.UPDATE.MERGE等DML语句执行后的信息时使用,合理使用returning能够 ...
- Python中对时间日期的处理方法简单汇总
这篇文章主要介绍了Python实用日期时间处理方法汇总,本文讲解了获取当前datetime.获取当天date.获取明天/前N天.获取当天开始和结束时间(00:00:00 23:59:59).获取两个d ...
- mssqlserver数据导出到另外一个数据库
mssqlserver数据导出到另外一个数据库 准备源数据库,找到想要导出的数据库,右键选择"任务"再选择"导出数据" 设置源数据库信息 3.设置目标数据库,导 ...
- RabbitMQ调试与测试工具-v1.0.1 -提供下载测试与使用
最近几天在看RabbitMQ,所以发了两天时间写了一个调试和测试工具.方便使用. 下载地址:RabbitMQTool-V1.0.1.zip
- Ubuntu 15.1 unity在顶部面板显示系统CPU/内存/网络速度
全部的文件:http://files.cnblogs.com/files/xiaobo-Linux/ubuntu%E6%98%BE%E7%A4%BA%E7%B3%BB%E7%BB%9F%E7%BD%9 ...
- SCNU 2015ACM新生赛初赛【1006. 3D打印】解题报告
题目链接详见SCNU 2015新生网络赛 1006. 3D打印 .出题思路来自codevs 3288. 积木大赛,属于模拟题. 首先我们把“选择从第L部分到第R部分”理 ...