首页 > 其他分享 >回文自动机(PAM)学习笔记

回文自动机(PAM)学习笔记

时间:2023-08-26 16:22:06浏览次数:40  
标签:bb 后缀 ll 串为 fail 自动机 PAM 回文

传送门

我认为理解回文自动机需要图,以\(abbaabba\)为例,它的回文树是这样的:

令树上的每一个点为一个回文串,其中,\(1\)为根的树中的点回文串长度为奇数,且最中间的那个字母就是\(1\)连向其他点的的边的字母,而\(0\)为根的树中的点回文串长度为偶数。

举点例子吧:点\(2\)的回文串为\(a\),点\(3\)的回文串为\(b\),点\(4\)的回文串为\(bb\),点\(5\)的回文串为\(abba\),点\(8\)的回文串为\(bbaabb\)

规律很明显,但我不会表达(逃),简单来说,感性理解,就是深度越小的边,它代表的字母位置在越里面。

考虑构造出这种回文树

引入\(fail\)数组:

再来一张图:

其中,\(fail\)数组指向的是该回文串中的最长回文后缀

很好理解,自己看

对于\(abb\)来说,若新插入了\(a\),如何更新回文树?

第一步:找到\(abb\)的最长回文后缀,即\(bb\),这个已经找到了,是上次更新回文树的时候

第二步:找到\(bb\)的前一个字母,即\(a\),与插入的字母,即\(a\)比较,若相同,则在表示回文\(bb\)的点后面连一条\(a\)的边,表示\(abba\),然后去更新\(fail\)数组,若不相同,则寻找\(bb\)的最长回文后缀,重复上述操作,知道可以或已经没有最长回文后缀为止。

考虑更新\(fail\)数组,这个与上述步骤相似,不同的只有要从\(bb\)的最长回文后缀开始找,即\(b\),理由是防止最长回文后缀是自己,而且是最长回文后缀

时间复杂度,对于一个新插入的字母,我们最多新增一个节点,总共最多有\(n\)个节点,而我们在枚举上述步骤时失配只会往前跳,所以总共条\(n\)次,所以时间复杂度是\(O(n)\)

上代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=2e6+50;
char s[N];
ll n,len[N],fail[N],last,tot=1,cur,trie[N][26],pos,num[N];
ll getfail(ll x,ll i)
{
	while(i-len[x]-1<0||s[i-len[x]-1]!=s[i]) x=fail[x];
	return x;
}
int main()
{
	scanf("%s",s);
	n=strlen(s);
	fail[0]=1,len[1]=-1;
	for(ll i=0;i<n;i++)
	{
		if(i!=0) s[i]=(s[i]+last-97)%26+97;
		pos=getfail(cur,i);
		if(!trie[pos][s[i]-'a'])
		{
			fail[++tot]=trie[getfail(fail[pos],i)][s[i]-'a'];
			trie[pos][s[i]-'a']=tot;
			len[tot]=len[pos]+2;
			num[tot]=num[fail[tot]]+1;
		}
		cur=trie[pos][s[i]-'a'];
		last=num[cur];
		printf("%lld ",last);
	}
	return 0;
}

标签:bb,后缀,ll,串为,fail,自动机,PAM,回文
From: https://www.cnblogs.com/pengchujie/p/17658967.html

相关文章

  • LeetCode 131. 分割回文串
    题目链接:LeetCode131.分割回文串题意:给你一个字符串s,请你将s分割成一些子串,使每个子串都是回文串。返回s所有可能的分割方案。回文串是正着读和反着读都一样的字符串。解题思路:dfs算法的过程其实就是一棵递归树,所有的dfs算法的步骤大概有以下几步:找到中止条件:即......
  • 【学习笔记】Manacher(马拉车)求回文子串
    点击查看目录目录参考资料与图片来源算法思路具体实现例题解题参考资料与图片来源参考博客我觉得这个博客讲的不好,他只讲看规律得到的结论,原因却不说,怪。参考博客2oi-wiki算法思路对于长度可能为奇可能为偶的情况,首先要预处理字符串,在每个字符左右增加一个无关字符#。......
  • AC自动机
    AC自动机本质上是KMP+Trie。每个节点存储的\(ne\)类似于KMP,表示最长公共前后缀(前缀可以是从根出发的任意一条路径)。代码可以从KMP一一对应过来。有Trie图优化,本质上可以直接背代码。#include<cstdio>#include<cstring>usingnamespacestd;#defineEdfor(inti=h[......
  • R语言lasso惩罚稀疏加法(相加)模型SPAM拟合非线性数据和可视化
    全文链接:https://tecdat.cn/?p=33462原文出处:拓端数据部落公众号本文将关注R语言中的LASSO(LeastAbsoluteShrinkageandSelectionOperator)惩罚稀疏加法模型(SparseAdditiveModel,简称SPAM)。SPAM是一种用于拟合非线性数据的强大工具,它可以通过估计非线性函数的加法组件来捕捉......
  • YACS 2023年8月月赛 乙组 T1 最长回文 题解
    题目链接小清新的区间DP题。看到数据范围以及回文一眼盯真得到是区间DP。设$f[i][j]$为区间$[i,j]$成为回文串最少要经过几次操作,转移一个个看。首先可以删掉第$j$个,$f[i][j]=\min(f[i][j],f[i][j-1]+1)$,同理也可以删掉第$i$个,$f[i][j]=\min(f[i][j],f[i+1][j]+1)$......
  • 「Note」字符串方向 - 自动机相关f
    1.AC自动机ACAM1.1.介绍AC自动机用于解决多模式串匹配问题,例如求多个模式串在文本串中的出现次数。显著地,它的应用实际上非常广泛。借助KMP的思想,我们对Trie树上的每个节点构造其失配指针\(fail_i\),指向对于当前字符串的最长后缀(其他(前缀)作为当前串后缀的最长的一个),......
  • [Luogu P8716] 回文日期 题解
    STEP1:分析题目大意:给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。这一题一眼看出是P2010的升级版,所以要先考虑到超时问题,因为如果一天一天地枚举,时间复杂度会非常高,所以我们不能直接枚举。因为题目只要"回文",所以我们只......
  • 第11周项目6-回文、素数(4)(5)
    问题及代码:/**Copyright(c)2014,烟台大学计算机学院*Allrightsreserved.*文件名称:MADE44.cpp*作者:孙化龙*完成日期:2014年11月6日*版本号:v1.0**问题描述:多文件组织程序*/#include<iostream>usingnamespacestd;intreverse(intx);boolisPrime......
  • dp-最长回文子序列
    最长回文子序列算法导论3rd-15.2问题描述回文:palindrome,是正序和逆序完全相同的非空字符串一个字符串有许多子序列,可以通过删除某些字符而变成回文字符串,字符串“cabbeaf”,删掉‘c’、'e'、‘f’后剩下的子串“abba”就是回文字符串,也是其中最长的回文子序列。在一个给定的......
  • #yyds干货盘点# LeetCode程序员面试金典:最短回文串
    题目:给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 示例1:输入:s="aacecaaa"输出:"aaacecaaa"示例2:输入:s="abcd"输出:"dcbabcd"代码实现:classSolution{publicStringshortestPalindrome(Strings){......