回文自动机pam
目的:类似回文Trie树+ac自动机,可以用来统计一些其他的回文串相关的量
复杂度:O(nlogn)
https://blog.csdn.net/Lolierl/article/details/99971257
https://www.luogu.org/problem/P5496
求出以每个位置结尾的回文子串个数,强制在线
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2e6+;
struct pam_trie
{
int ch[];
int fail,len,num;
};
struct pam
{
pam_trie b[maxn];
int n,length,last,cnt,s[maxn];
char c[maxn];
pam()
{
b[].len=;b[].len=-;
b[].fail=;b[].fail=;
last=;
cnt=;
}
void read()
{
scanf("%s",c+);
length=strlen(c+);
}
int get_fail(int x)
{
while(s[n-b[x].len-]!=s[n])x=b[x].fail;
return x;
}
void insert()
{
int p=get_fail(last);
if(!b[p].ch[s[n]])
{
b[++cnt].len=b[p].len+;
b[cnt].fail=b[get_fail(b[p].fail)].ch[s[n]];
//b[cnt].num=b[b[cnt].fail].num+1;
b[p].ch[s[n]]=cnt;
}
last=b[p].ch[s[n]];
b[last].num=b[b[last].fail].num+;
}
void solve()
{
int k=;
s[]=;
for(n=;n<=length;n++)
{
c[n]=(c[n]-+k)%+;
s[n]=c[n]-'a';
insert();
printf("%d ",b[last].num);
k=b[last].num;
}
}
}P; int main()
{
P.read();
P.solve();
return ;
}
https://www.luogu.org/problem/P3649
求回文子串出现次数*长度的最大值
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=3e5+;
struct pam_trie
{
int ch[];
int fail,len,sum;
};
struct pam
{
pam_trie b[maxn];
int n,length,last,cnt,s[maxn];
char c[maxn];
long long ans;
pam()
{
b[].len=;b[].len=-;
b[].fail=;b[].fail=;
last=;
cnt=;
}
void read()
{
scanf("%s",c+);
length=strlen(c+);
}
int get_fail(int x)
{
while(s[n-b[x].len-]!=s[n])x=b[x].fail;
return x;
}
void insert()
{
int p=get_fail(last);
if(!b[p].ch[s[n]])
{
b[++cnt].len=b[p].len+;
b[cnt].fail=b[get_fail(b[p].fail)].ch[s[n]];
b[p].ch[s[n]]=cnt;
}
last=b[p].ch[s[n]];
b[last].sum++;
}
void solve()
{
s[]=;
for(n=;n<=length;n++)
{
s[n]=c[n]-'a';
insert();
}
ans=;
for(int i=cnt;i>;i--)
{
b[b[i].fail].sum+=b[i].sum;
ans=max(ans,1ll*b[i].sum*b[i].len);
}
printf("%lld\n",ans);
}
}P;
int main()
{
P.read();
P.solve();
}
https://www.luogu.org/problem/P4287
计算串的最长双倍回文子串的长度,tips:fail指针指向当前节点所表示的回文串的最长回文后缀
#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=5e5+;
struct pam_trie
{
int ch[];
int fail,len,sum;
};
struct pam
{
pam_trie b[maxn];
int n,length,last,cnt,s[maxn];
char c[maxn];
pam()
{
b[].len=;b[].len=-;
b[].fail=;b[].fail=;
last=;cnt=;
}
void read()
{
scanf("%d",&length);
scanf("%s",c+);
}
int get_fail(int x)
{
while(s[n-b[x].len-]!=s[n])x=b[x].fail;
return x;
}
void insert()
{
int p=get_fail(last);
if(!b[p].ch[s[n]])
{
b[++cnt].len=b[p].len+;
b[cnt].fail=b[get_fail(b[p].fail)].ch[s[n]];
b[p].ch[s[n]]=cnt;
}
last=b[p].ch[s[n]];
b[last].sum++;
}
void solve()
{
s[]=;
for(n=;n<=length;n++)
{
s[n]=c[n]-'a';
insert();
}
int ans=;
for(int i=cnt;i>;i--)
{
int pos=i;
if(b[i].len%!=||b[i].len<=ans)continue;
while(*b[pos].len>b[i].len)pos=b[pos].fail;
if(*b[pos].len==b[i].len)ans=b[i].len;
}
printf("%d\n",ans);
}
}P;
int main()
{
P.read();
P.solve();
return ;
}
ICPC 2018 南京 Mediocre String Problem,用回文自动机来求出以每个位置结尾的回文子串个数,再进行exkmp
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e6+;
struct pam_trie
{
int ch[];
int fail,len,num;
};
int res[maxn];
char s1[maxn],s2[maxn],t[maxn]; struct pam
{
pam_trie b[maxn];
int n,last,cnt,s[maxn],length;
pam()
{
b[].len=;b[].len=-;
b[].fail=;b[].fail=;
last=;
cnt=;
}
int get_fail(int x)
{
while(s[n-b[x].len-]!=s[n])x=b[x].fail;
return x;
}
int insert()
{
int p=get_fail(last);
if(!b[p].ch[s[n]])
{
b[++cnt].len=b[p].len+;
b[cnt].fail=b[get_fail(b[p].fail)].ch[s[n]];
b[p].ch[s[n]]=cnt;
}
last=b[p].ch[s[n]];
b[last].num=b[b[last].fail].num+;
return b[last].num;
}
void solve()
{
s[]=;
length=strlen(s1);
for(n=;n<=length;n++)
{
s[n]=s1[n-]-'a';
res[n-]=insert();
}
}
}P; int Next[maxn],extend[maxn];
void get_next(char *s)
{
int n=strlen(s),i,j,k=;
for(j=;+j<n&&s[j]==s[+j];j++);
Next[]=j;
for(i=;i<n;i++)
{
int len=k+Next[k],L=Next[i-k];
if(L<len-i)Next[i]=L;
else
{
for(j=max(,len-i);i+j<n&&s[j]==s[i+j];j++);
Next[i]=j;
k=i;
}
}
Next[]=n;
}
void ex_kmp(char *T,char *s)
{
int n=strlen(T),m=strlen(s),i,j,k;
for(j=;j<n&&j<m&&T[j]==s[j];j++);
extend[]=j;
k=;
for(i=;i<n;i++)
{
int len=k+extend[k],L=Next[i-k];
if(L<len-i)extend[i]=L;
else
{
for(j=max(,len-i);j<m&&i+j<n&&s[j]==T[i+j];j++);
extend[i]=j;
k=i;
}
}
} int main()
{
scanf("%s",s1);
scanf("%s",t);
int lens=strlen(s1); reverse(s1,s1+lens);
for(int i=;i<lens;i++)s2[i]=s1[i];
s2[lens]='\0'; get_next(t);
ex_kmp(s2,t);
long long ans=;
P.solve();
for(int i=;i<lens;i++)
{
ans+=1ll*extend[i]*res[i-];
}
printf("%lld\n",ans);
return ;
}
...
回文自动机pam的更多相关文章
- 回文树(回文自动机PAM)小结
回文树学习博客:lwfcgz poursoul 边写边更新,大概会把回文树总结在一个博客里吧... 回文树的功能 假设我们有一个串S,S下标从0开始,则回文树能做到如下几点: 1.求串S前缀0~ ...
- 回文树/回文自动机(PAM)学习笔记
回文树(也就是回文自动机)实际上是奇偶两棵树,每一个节点代表一个本质不同的回文子串(一棵树上的串长度全部是奇数,另一棵全部是偶数),原串中每一个本质不同的回文子串都在树上出现一次且仅一次. 一个节点的 ...
- 回文自动机(PAM) 入门讲解
处理回文串,Manacher算法也是很不错,但在有些问题的处理上比较麻烦,比如求本质不同的子串的数量还需要结合后缀数组才能解决.今天的们介绍一种能够方便的解决关于回文串的问题的算法--PAM. 一些功 ...
- 洛谷P5496 回文自动机【PAM】模板
回文自动机模板 1.一个串的本质不同的回文串数量是\(O(n)\)级别的 2.回文自动机的状态数不超过串长,且状态数等于本质不同的回文串数量,除了奇偶两个根节点 3.如何统计所有回文串的数量,类似后缀 ...
- 【XSY2715】回文串 树链剖分 回文自动机
题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(tra ...
- 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)
模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...
- 【回文自动机】bzoj3676 [Apio2014]回文串
回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i ...
- 省选算法学习-回文自动机 && 回文树
前置知识 首先你得会manacher,并理解manacher为什么是对的(不用理解为什么它是$O(n)$,这个大概记住就好了,不过理解了更方便做$PAM$的题) 什么是回文自动机? 回文自动机(Pal ...
- 洛谷P4287 [SHOI2011]双倍回文(回文自动机)
传送门 听说有大佬用manacher$O(n)$过此题……太强啦…… 说一下PAM的做法吧.(看了题解之后发现)蛮简单的 我们肯定要先建出回文自动机的 然后如果是枚举每一个节点暴跳fail指针肯定得T ...
随机推荐
- PHP经典算法题
1.百钱买百鸡 公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用100文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱. 分析:估计现在小学生都能手工推 ...
- Vue img的src使用数据绑定不显示
不少人在vue的开发中遇到这样一个问题: img的src属性绑定url变量,然而图片加载失败. <img src="{{ imgUrl }}"/> 原因:写法错误 解决 ...
- 基于Windows下永久破解jetbrains公司的系列产品(Idea, pycharm,clion,phpstorm)
基于Windows下永久破解jetbrains公司的系列产品(Idea, pycharm,clion,phpstorm): PS : 有能力的建议购买正版,好吧. PS:均针对其对应的2018.3.1 ...
- django_1:配置文件
工程下: settings.py(建议设置成如下) DATABASES #数据库配置 DEBUG = True ...
- 记一个vue-resource请求的低级错误
对于初学的小菜鸡,经常会犯一些低级错误. 现在记录一下我在使用vue-resource发送post请求时的一个低级错误: window.BaseURL = '127.0.0.1:8888'; 8888 ...
- PostGIS mysql_fdw使用(Linux)
##前文讲了mysql_fdw的安装,此文主要讲mysql_fdw的配置以及使用 ##附上前文链接:https://www.cnblogs.com/giser-s/p/11208803.html 背景 ...
- 20191019-3 alpha week 2/2 Scrum立会报告+燃尽图 03
此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/9799 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩昊 ...
- Vue 幸运大转盘
转盘抽奖主要有两种,指针转动和转盘转动,个人觉得转盘转动比较好看点,指针转动看着头晕,转盘转动时指针是在转盘的中间位置,这里要用到css的transform属性和transition属性,这两个因为不 ...
- SpringBoot 项目脚手架
写在前面 之前也一直很少有写SpringBoot项目相关的文章,今天 准备整理一个我自己初始化SpringBoot项目时的一个脚手架,便于自己后面查阅.因为SpringBoot的约定大于配置,在整合各 ...
- 安卓Android碎片fragment实现静态加载
静态加载好后的界面如下,两个碎片分别位于一个活动的左边和右边: 左边和右边分别为一个碎片,这两个碎片正好将一整个活动布满.一个活动当中可以拥有多个碎片,碎片的含义就是可以在同一个UI界面下,将这个界面 ...