首页 > 其他分享 >回文自动机

回文自动机

时间:2023-04-05 21:48:49浏览次数:28  
标签:子串 结点 cur fail 自动机 PAM 回文

概念

回文自动机,PAM,又叫回文树。

用于处理和回文子串有关的问题,和 SAM 有一些类似的地方。

构造

首先 PAM 上的每个结点代表原串的一个回文子串。

根据神秘结论,原串本质不同的回文子串至多有 \(n\) 个,也就是 PAM 的点数至多是 \(n + 2\),边数至多是 \(n\).

考虑到回文串的奇偶性会导致一些讨论,考虑给奇数长度和偶数长度的回文子串分别构造奇根和偶根。

指针全部指向奇根,奇根长度为 \(-1\).

这样出现新字符的时候就可以直接挂到奇根。

然后考虑 PAM 上的转移。

从上到下的转移意味着在父结点代表的串中首尾各加上指定的字符。

从下到上的转移 fail 意味着该结点的最长回文真后缀对应的结点。

构造和 SAM 一样考虑增量,每次向上找到最后一个可以和当前位置匹配的结点转移就行。

向上跳相当于消耗已有的势能,势能分析得构造 PAM 的时间复杂度是 \(O(n)\).

有时候会需要知道某串中长度小于一半的回文子串,可以另外维护一个指针指向对应的子串。更新暴力向上跳就行。

void build() { cur = fail[0] = fail[1] = 1, len[1] = -1; }

int get_fail(int nd, int p)
{
	while (s[p - len[nd] - 1] != s[p]) nd = fail[nd];
	return nd;
}

void insert(int p)
{
	int x = get_fail(lst, p), c = ch_id(s[p]);
	if (!son[x][c])
	{
		cur++;
		len[cur] = len[x] + 2, fail[cur] = son[get_fail(fail[x], p)][c];
		son[x][c] = cur;
		if (len[cur] <= 2) trans[cur] = fail[cur];
		else
		{
			int tr = trans[x];
			while ((s[p - len[tr] - 1] != s[p]) || ((len[tr] + 2) * 2 > len[cur])) tr = fail[tr];
			trans[cur] = son[tr][c];
		}
	}
	lst = son[x][c], cnt[lst]++;
}

套路

本质不同回文子串个数

等价于 PAM 的总点数 - 2,也就是除去奇根和偶根。

回文子串出现次数

类似 SAM,考虑在回文树上求子树和。

回文树上 dp

例题:P4762 [CERC2014]Virus synthesis

考虑令 \(f[i]\) 表示构造回文树上结点 \(i\) 对应子串需要的最少次数,\(trans[i]\) 表示结点 \(i\) 长度不超过一半的最长回文真后缀结点。

讨论一下树边的转移和 trans 有关的转移就行。

k 阶回文子串计数

例题:CF835D Palindromic characteristics

考虑讨论 \(i\) 和 \(trans[i]\) 的长度转移。

咕咕咕,明天继续更。

标签:子串,结点,cur,fail,自动机,PAM,回文
From: https://www.cnblogs.com/lingspace/p/pam.html

相关文章

  • 39. 组合总和 40.组合总和II 131.分割回文串
    39.组合总和自己写的回溯算法:classSolution{List<List<Integer>>list;LinkedList<Integer>res;publicList<List<Integer>>combinationSum(int[]candidates,inttarget){list=newArrayList<>();res=......
  • 洛谷P1217 [USACO1.5]回文质数 Prime Palindromes
    #include<bits/stdc++.h>usingnamespacestd;inta,b;boolzs(intx){if(x%2>0){for(inti=3;i<x;i+=2)if(x%i==0)returnfalse;returntrue;}elsereturnfalse;}boolhws(intx......
  • 后缀自动机
    后缀自动机是通过一个DAG图来存储的,使空间更小,后缀自动机中最关键的一项技术叫做后缀链。1.建立SAMvoidinsert(intc){ newNode(t[last].len+1); intp=last,cur=sz; while(p!=-1&&!t[p].son[c])t[p].son[c]=cur,p=t[p].father; if(p==-1)t[cur].father=0; else{ int......
  • 【LBLD】如何判断回文链表
    【LBLD】如何判断回文链表判断回文单链表/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val(x),next(nullptr){}*ListNode(intx,......
  • U兑换TRX的自动机器人怎么开发?一篇文章教你部署
    TRX兑币机器人现在在telegram电报上非常流行了,很多用户都开始接受了这样的兑币方式。相对于使用币安或者火币来说,用户通过机器人兑换TRX更加方便快捷,不需要充币提币等......
  • 最长回文字串之暴力解法
    最长回文字串是一个典型的算法问题,首先要搞清楚什么是回文。回文,故名思义就是对称的文字,比如“ABA”,比如“ABABC”中的“AB“。题目如下:给你一个字符串s,找到s中最长......
  • 力扣---面试题 01.04. 回文排列
    给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。回文串不一定是字典当中的单词。......
  • AC自动机相关模板
    P5357#include<bits/stdc++.h>#defineintlonglong#defineN200005usingnamespacestd;intn,cnt[N]={0};strings[N],t;map<string,int>apr;string......
  • 学习笔记:AC自动机
    AC自动机是一种多模匹配算法,AC自动机常常用于多模式串,单文本串的匹配算法。在此之前,你应当学会KMP&Trie。我们先给一组例子:abcdbcdcddacad这是这组例子建成的......
  • day27 打卡39. 组合总和 40.组合总和II 131.分割回文串
    day27打卡39.组合总和40.组合总和II131.分割回文串39.组合总和39题目链接classSolution{List<List<Integer>>result=newArrayList<>();LinkedList......