首页 > 编程语言 >算法学习—————PAM回文自动机

算法学习—————PAM回文自动机

时间:2022-09-06 18:56:53浏览次数:47  
标签:ch pos PAM fail 自动机 preNode pam 回文

时隔一年,第一次学习新的算法

原理和AC自动机差不多

基本思想:

  1. 两棵树分别代表奇偶

  2. 在一个回文串两边同时填上相同字符可以得到另一个回文串,以此构建两棵树

树上维护信息:

  1. 节点表示的回文串为当前位置的最长回文串

  2. 节点上维护当前位置最长回文串的长度,fail指针(当前回文串的最长回文后缀)

如何维护:

  1. 若可以扩展,长度+2 判断条件: s[pos-len-1] == s[pos],否则跳fail

  2. 如何维护fail? 找到第一个可以扩展的位置,连出c边的点即是fail的指向

代码为洛谷模板题

当前节点的答案为他的fail的答案+1(可想而知,感觉而知)

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define O(x) cout<<#x<<" "<<x<<endl;
#define B cout<<"Breakpoint"<<endl;
using namespace std;
int read(){
	int x = 1,a = 0;char ch = getchar();
	while (ch < '0'||ch > '9'){if (ch == '-') x = -1;ch = getchar();}
	while (ch >= '0'&&ch <= '9'){a = a*10+ch-'0';ch = getchar();}
	return x*a;
}
const int maxn = 5e5+10;
struct node{
	int len,fail,ch[30];
}pam[maxn];
char s[maxn];
int n,preNode = 2,tot = 2;
int ans[maxn];
void insert(int pos){
	if (pos > 1) s[pos] =  (s[pos] - 97 + ans[preNode]) % 26 + 97;
	int c = s[pos]-'a';
	while (s[pos - pam[preNode].len - 1] != s[pos]) preNode = pam[preNode].fail;
	if (pam[preNode].ch[c]) preNode = pam[preNode].ch[c];
	else{
		int nowNode = ++tot;
		pam[preNode].ch[c] = nowNode;
		pam[nowNode].len = pam[preNode].len + 2;
		if (preNode == 1) pam[nowNode].fail = 2; 
		else{
			for (preNode = pam[preNode].fail;s[pos - pam[preNode].len - 1] != s[pos];preNode = pam[preNode].fail);
			pam[nowNode].fail = pam[preNode].ch[c];
		}
		preNode = nowNode;
	}
	ans[preNode] = ans[pam[preNode].fail] + 1;
	cout<<ans[preNode]<<" ";
}
int main(){
	scanf ("%s",s+1);
	n = strlen(s+1);
	pam[1].len = -1,pam[2].len = 0;
	pam[2].fail = 1;
	for (int i = 1;i <= n;i++) insert(i);
	return 0;
}

标签:ch,pos,PAM,fail,自动机,preNode,pam,回文
From: https://www.cnblogs.com/little-uu/p/16662959.html

相关文章

  • leetcode 6356 最长回文子串长度,最长回文子串 C/C++ 动态规划方案 同样的用例,测试执
    对dp变量需要执行初始化,否者LeetCode会出现同样的用例,单独执行可以通过,提交代码执行不通过的情况。 下面是找最长回文串的动态规划代码。class Solution {public:......
  • 【luogu P5826】【模板】子序列自动机
    【模板】子序列自动机题目链接:luoguP5826题目大意给你一个序列,每次再给你一个序列,问你新的序列是不是一开始的序列的子序列。思路如果字符少不难想象到一个\(f_{i,j......
  • papamelon 305. 求和方案 Sumsets
    https://www.papamelon.com/problem/305给你一个数N,只能用2的幂次求和组成,问总共有多少种方案.输入包含多组测试数据,输入以EOF作为结束标志.每组测试数据包含一个......
  • LeetCode 131 分割回文串
    classSolution{public:vector<vector<string>>res;vector<string>path;boolis(strings,intstart,intend){for(inti=start,j=......
  • 信息学一本通 1309:【例1.6】回文数(Noip1999)
    时间限制:1000ms      内存限制:65536KB提交数:17647   通过数:7270【题目描述】若一个数(首位不为零)从左向右读与从右向左读都是一样,我们就将其......
  • letcode算法--7.回文数
    给你一个整数x,如果x是一个回文整数,返回true;否则,返回false。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121是回文,而123不是。来源:力扣(Leet......
  • 数字分离及回文数
    1.统计n的位数intcont(intn)//统计n的位数{ints=0;while(n>0){s++;n/=10;}returns;}2.统计n的数字和intsum(in......
  • leetcode 409 Longest Palindrome 最长回文串(简单)
    一、题目大意给定一个包含大写字母和小写字母的字符串s,返回通过这些字母构造成的最长的回文串。在构造过程中,请注意区分大小写。比如"Aa"不能当做一个回文字符......
  • P3808 【模板】AC 自动机(简单版)
    题目链接代码#include<iostream>#include<cstdio>usingnamespacestd;constintN=1000010;intn;charstr[N];inttr[N][26],cnt[N],idx;intfail[N],q[N];......
  • C20220725T3 回文
    给定字符串\(s\),求\(s_{l,r}\)中回文串个数。多组询问,\(|s|\leq5000\),\(T\leq10^5\)。首先介绍\(O(n\timesT)\)的离谱做法(竟然没卡掉),先跑\(Manachar\),然......