• 回文自动机学习笔记


    回文自动机学习笔记

    和AC自动机差不多,回文自动机每个节点的含义表示在它的父节点两侧各加上一个儿子字符。并且我们也要维护一个fail指针表示这个节点的最长回文后缀

    PAM有两个根,奇根和偶根,

    偶根的节点编号为 (0),所代表的回文串的长度为 (0),fail指针指向奇根

    奇根的节点编号为 (1),所代表的回文串的长度为 (-1),fail指针指向自身

    fail指针

    fail指针表示这个节点的最长回文后缀,构建方法是往上跳fail直到两端能+1。

    关于新建节点,也是往上跳fail,没有出边就新建点,并且新节点长度等于这个节点长度+2。

    #include<bits/stdc++.h>
    #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
    #define ROF(i,a,b) for(int i=(a);i>=(b);--i) 
    const int inf = 1e9;
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x; 
    }
    const int N = 1e6+200;
    char s[N];
    	int tot,las;
    	int fail[N],len[N],pos[N];
    	int ch[N][26],num[N];
    	void init(){
    		las=0,tot=1;
    		len[0]=0,fail[0]=1;
    		len[1]=-1,fail[1]=0;
    	}
    	void add(int c,int id){
    		int p=las;
    		for(;s[id]!=s[id-len[p]-1];p=fail[p]);
    		
    		if(!ch[p][c]){
    			int np=++tot,q=fail[p];len[np]=len[p]+2;
    			for(;s[id]!=s[id-len[q]-1];q=fail[q]);
    			fail[np]=ch[q][c]; ch[p][c]=np;
    			num[np]=num[fail[np]]+1;
    		}
    		las=ch[p][c]; 
    	}
    int main(){
    	scanf("%s",s+1);
    	init();
    	int pre=0,l=strlen(s+1);
    		FOR(i,1,l){
    			s[i] = (s[i] - 97 + pre) % 26 + 97; 
    			add(s[i]-'a',i);
    			pos[i]=las;
    			printf("%d ",num[las]);
    			pre=num[las];
    		}
    	return 0;
    }
    
  • 相关阅读:
    Object.Instantiate 实例
    .idata数据的解析
    数据结构-静态链表
    数据结构-循环链表
    Android---两个视图间的淡入淡出
    HDU 4597 Play Game 2013 ACM-ICPC吉林通化全国邀请赛H题
    Android 编译时出现r cannot be resolved to a variable
    找工作笔试面试那些事儿(5)---构造函数、析构函数和赋值函数
    SFINAE 模板替换失败而非报错的应用
    模板实参推导 & xx_cast的实现
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/13187974.html
Copyright © 2020-2023  润新知