【BZOJ3676&UOJ103】回文串(manacher,Trie)
题意:考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度。
请你求出s的所有回文子串中的最大出现值。
len<=300000
思路:
做法一:manacher+Trie
鸣谢UOJ上ID为nothing100的小哥(小姐姐?)
学P一时爽,转C火葬场
考虑不同的回文子串中间也是有子串关系的,并且互不包含的极长回文子串的数量是O(n)级别的
所以可先用manacher算出每个位置的最长回文半径
将它们表示成一棵树的形状,一个节点的儿子是它所代表的子串向两侧扩展一个相同字母的串
判断是否是父子关系可以用hash
最后dfs一遍求子树大小就行了,注意需要双hash,C党hash后可以用map和makepair
讲道理C党到这里就能做了,问题我是P党
考虑到刚才那棵树,如果你每个串都只取后半段,那么它是一颗Trie树
所以可以用和刚才类似的方法,而且并不需要hash
manacher过程中
i关于id的对称中心j,mx>i时:
如果p[j]>mx-i则p[i]需要从p[j]开始退格,依次删除最后一个字符直到到达mx-i为止
否则p[i]即为p[j]
mx<=i时说明当前只有i一个字符,就从头开始扩展
UOJ上过了,BZ上没过,残念……
var map:array[..,..]of longint;
fa,size,p,f,a,h:array[..]of longint;
n,m,i,j,mx,id,cnt,len:longint;
ans:int64;
ch:char; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; function max(x,y:int64):int64;
begin
if x>y then exit(x);
exit(y);
end; function get(x,y:longint):longint;
begin
if map[x,y]= then
begin
inc(cnt);
fa[cnt]:=x;
map[x,y]:=cnt;
end;
exit(map[x,y]);
end; procedure dfs(u,ch:longint;dep:int64);
var i,v:longint;
begin
for i:= to do
begin
v:=map[u,i];
if v> then
begin
dfs(v,i,dep+);
size[u]:=size[u]+size[v];
end;
end;
if ch< then ans:=max(ans,dep*size[u]);
end; begin
assign(input,'bzoj3676.in'); reset(input);
assign(output,'bzoj3676.out'); rewrite(output); n:=; a[]:=; a[]:=;
while not eoln do
begin
read(ch);
inc(n); a[n]:=ord(ch)-ord('a')+;
inc(n); a[n]:=;
end;
inc(n); a[n]:=;
mx:=; id:=; cnt:=;
for i:= to n- do
begin
if mx>i then
begin
p[i]:=p[id*-i]; h[i]:=h[id*-i];
if p[i]>mx-i then
begin
for j:=p[i]- downto mx-i do h[i]:=fa[h[i]];
p[i]:=mx-i;
end;
end
else
begin
h[i]:=get(,a[i]);
p[i]:=;
end;
while a[i-p[i]]=a[i+p[i]] do
begin
h[i]:=get(h[i],a[i-p[i]]);
inc(p[i]);
end;
if p[i]+i>mx then
begin
mx:=p[i]+i; id:=i;
end;
inc(size[h[i]]);
end;
dfs(,,);
writeln(ans);
close(input);
close(output);
end.
做法2:回文自动机板子
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,int>P;
#define N 300010
#define M 210000
#define fi first
#define se second
#define MP make_pair
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const int MOD=,inv2=(MOD+)/;
double eps=1e-;
int INF=<<;
ll inf=5e13;
int dx[]={-,,,};
int dy[]={,,-,}; char s[N];
int n; struct pam
{
int q,p,id,cnt[N],num[N],f[N],len[N],t[N][]; pam()
{
id=; f[]=f[]=; len[]=-;
} void add(int x,int n)
{
while(s[n-len[p]-]!=s[n]) p=f[p];
if(!t[p][x])
{
int q=++id,k=f[p];
len[q]=len[p]+;
while(s[n-len[k]-]!=s[n]) k=f[k];
f[q]=t[k][x];
t[p][x]=q;
num[q]=num[f[q]]+;
}
p=t[p][x];
cnt[p]++;
} void solve()
{
ll ans=;
per(i,id,)
{
cnt[f[i]]+=cnt[i];
ans=max(ans,1ll*cnt[i]*len[i]);
}
printf("%lld\n",ans);
} }pam; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} int main()
{
//freopen("1.in","r",stdin); scanf("%s",s+);
n=strlen(s+);
rep(i,,n) pam.add(s[i]-'a',i);
pam.solve();
return ;
}
【BZOJ3676&UOJ103】回文串(manacher,Trie)的更多相关文章
- BZOJ3676 APIO2014 回文串 Manacher、SA
传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...
- [BZOJ3676][APIO2014]回文串(Manacher+SAM)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3097 Solved: 1408[Submit][Statu ...
- [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增
Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...
- [APIO2014] [Uoj103] [Bzoj3676] Palindromes回文串 [Manacher,后缀数组]
用Manacher算法枚举回文子串,每次在后缀数组排序后的后缀数组中二分,因为用某一后缀和其他子串分别求匹配的长度,匹配长度在排序后该后缀的两侧具有单调性(匹配长度为min{H[x]|i<=x& ...
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串
回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...
- BZOJ3676 APIO2014回文串(manacher+后缀自动机)
由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计.可以发现manacher时若右端点移动则找到了一个新回文串.注意这样会漏掉串长为1的情况,特判一下. 现在问 ...
- BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)
Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...
- 【回文串-Manacher】
Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 转:http://blog.sina.com.c ...
- BZOJ 2342 回文串-Manacher
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2342 思路:先跑一遍Manacher求出p[i]为每个位置为中心的回文半径,因为双倍回文串 ...
随机推荐
- css 实现 checkbox 大小调整
一般调整 checkbox 大小我们想到的是 width.height,可是设置后,发现是没有效的. 如微信小程序里面,checkbox 默认就很大,想设置小一点怎么办? transform: sca ...
- [Qt Creator 快速入门] 第5章 应用程序主窗口
对于日常见到的应用程序而言,许多都是基于主窗口的,主窗口中包含了菜单栏.工具栏.状态栏和中心区域等.这一章会详细介绍主窗口的每一个部分,还会涉及资源管理.富文本处理.拖放操作和文档打印等相关内容.重点 ...
- 【转】Linux系统编程---dup和dup2详解
正常的文件描述符: 在linux下,通过open打开以文件后,会返回一个文件描述符,文件描述符会指向一个文件表,文件表中的节点指针会指向节点表.看下图: 打开文件的内核数据结构 dup和dup2两个函 ...
- 429c Leha and Function
题目 解题报告 F(n, k)是在集合{1, 2, 3, ..., n}中所有的具有k个元素的子集中分别取最小值,相加后的期望. 例如:要求F(4, 2),根据定义有{1, 2}, {1, 3}, { ...
- 二分搜索 POJ 3258 River Hopscotch
题目传送门 /* 二分:搜索距离,判断时距离小于d的石头拿掉 */ #include <cstdio> #include <algorithm> #include <cs ...
- Q - Euclid in Manhattan(欧几里德距离==曼哈顿距离?)
Desciption Consider a set of n points in a 2-D plane with integer coordinates. There are various way ...
- Too many open files故障解决一例
Linux环境WebSphere输出日志: [// ::: EDT] 000090b7 SystemErr R Caused by: java.io.FileNotFoundException: /o ...
- cocos creator 场景如何透明,多个canvas层级显示
转载地址:https://forum.cocos.com/t/creator-canvas/55373/14 Creator 版本:1.7 目标平台:WEB MOBILE 项目需要,页面做了多个Can ...
- 几个不同的tab切换示例
上一篇<论tab切换的几种实现方法>中讲了tab切换的4种不同实现原理,那么,现在到理论联系实际的时候了,下面就写几个实例. 一.仿”中国人民大学“官网的tab切换,背景是图片,效果图如下 ...
- python爬虫(房天下)
房天下 import requests res = requests.get('http://esf.sz.fang.com/') #res.text from bs4 import Beautifu ...