zoukankan      html  css  js  c++  java
  • 回文自动机学习笔记

    回文自动机学习笔记

    和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;
    }
    
  • 相关阅读:
    2018年-2019年第二学期第七周C#学习个人总结
    2018年-2019年第二学期第六周C#学习个人总结
    2018年-2019年第二学期第五周C#学习个人总结
    2018年-2019年第二学期第四周C#学习个人总结
    2018年-2019年第二学期第三周C#学习个人总结
    2018年-2019年第二学期第二周C#学习个人总结
    本学期C#学习个人总结
    排球积分程序
    观后感
    最终总结
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/13187974.html
Copyright © 2011-2022 走看看