【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]为每个位置为中心的回文半径,因为双倍回文串 ...
随机推荐
- c++ swap函数
swap(a,b)也就是把a和b的值互换. 头文件:#include<algorithm>,swap要加using namespace std:
- 263 Ugly Number 丑数
编写程序判断给定的数是否为丑数.丑数就是只包含质因子 2, 3, 5 的正整数.例如, 6, 8 是丑数,而 14 不是,因为它包含了另外一个质因子 7.注意: 1 也可以被当做丑数. 输 ...
- [转]mysql update操作
转自:http://www.cnblogs.com/ggjucheng/archive/2012/11/06/2756392.html update语法 Single-table语法: UPDATE ...
- python __slots__ 详解(上篇)
转自:http://blog.csdn.net/sxingming/article/details/52892640 python中的new-style class要求继承Python中的一个内建类型 ...
- 十年后我不会log,还是活的很好啊
混迹于互联网也一两年了,出于喜爱与生活压力依然会从事很久.迟迟不写博客,大概是觉得知识与经验积累在笔记上时不时看看就好了,而实际情况是笔记很少翻,遇到问题搜博客和百度依然是首选,故开通博客记录自己工作 ...
- jstree的基本使用例子
var menu = (function() { var _menu = {data:{}, initMenu : function() { $.jstree.defaults.core.themes ...
- creator游戏开发基本语法
写的比较杂乱,类似随笔,随时可能往里面添加修改给lable文本赋值: this.ScoreNumber.getComponent(cc.Label).string = GAME_DATE.MMscor ...
- Jmeter的面板介绍
一.jmeter面板介绍,这里是5.1.1版本 1.jmeter面板大致分为菜单区,图标区,目录树以及详细配置区域. 2.大多数人用着英文的面板不太舒服,可以在options里切换jmeter的语言 ...
- php获取文件扩展名
<?php $path = 'http://www.wstmart.net/doc.html'; $ext = getExt($path); echo $ext; // 方法1 function ...
- 10Java Server Pages 隐式对象
Java Server Pages 隐式对象 JSP隐式对象是Web容器加载的一组类的实例,它不像一般的Java对象那样用“new”去获取实例,而是可以直接在JSP页面使用的对象.JSP提供的隐式对象 ...