【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陷阱和缺陷] 第7章 可移植性缺陷
C语言在许多不同的系统平台上都有实现.的确,使用C语言编写程序的一个首要原因就是,C程序能够方便地在不同的编程环境中移植. 不同的系统有不同的需求,因此我们应该能够预料到,机器不同则其上的C语 ...
- BFS POJ 3414 Pots
题目传送门 /* BFS:六种情况讨论一下,BFS轻松解决 起初我看有人用DFS,我写了一遍,TLE..还是用BFS,结果特判时出错,逗了好长时间 看别人的代码简直是受罪,还好自己终于发现自己代码的小 ...
- 全面学习ORACLE Scheduler特性(1)创建jobs
所谓出于job而胜于job,说的就是Oracle 10g后的新特性Scheduler啦.在10g环境中,ORACLE建议使用Scheduler替换普通的job,来管理任务的执行.其实,将Schedul ...
- Appium基于python unittest自动化测试并生成html测试报告
本文基于python单元测试框架unittest完成appium自动化测试,生成基于html可视化测试报告 代码示例: #利用unittest并生成测试报告 class Appium_test(uni ...
- 5步上手体验kettle快捷调度方式
https://my.oschina.net/u/944575/blog/1557410 kettle调度监控最佳实践 https://my.oschina.net/u/1026947/blog/15 ...
- MSSQLSERVER_3176
本文档已存档,并且将不进行维护. MSSQLSERVER_3176 SQL Server 2014 SQL Server 2012 ...
- oracle数据库跨库查询
create public database link mylink connect to orclname identified by orclpasswd using 'ORCL'; drop p ...
- npm换淘宝源 yarn换淘宝源
查询初始的源 npm get registry > https://registry.npmjs.org/ 设置淘宝源 npm config set registry http://regist ...
- HDU_3496_(二维费用背包)
Watch The Movie Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
- arx 插入图片
#include <ShLwApi.h> #pragma comment(lib, "ShLwApi.lib") //插入影像图 Acad::ErrorStatus i ...