【模板】回文自动机

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int mod=19930726;
struct node{
	int len,fail,ch[26],siz;
	friend bool operator <(node a,node b) {
		return a.len>b.len; 
	}
}prt[N];
int n,num,len,lst;
char s[N];
int getfail(int x) {
	while(s[n-prt[x].len-1]!=s[n]) x=prt[x].fail;
	return x;
}
void extand(int x) {
	int cur=getfail(lst); //时间复杂度分析:O(n) 
	int now=prt[cur].ch[x];
	if(!now) {
		now=++num;
		prt[now].len=prt[cur].len+2;
		prt[now].fail=prt[getfail(prt[cur].fail)].ch[x]; //由于外层是O(n),而内层跳fail,外层也会减小,所以可以看作外层的从动点,是比外层循环小的 
		prt[cur].ch[x]=now; //这一句要写在上一句后面,因为要保证 ch[x]=0 ,此时cur=-1 
	}
	prt[now].siz++;
	lst=now;
}
void calc() {
	for(int i=num;i>=2;i--) //长的字符串一定包括短的字符串 
	    prt[prt[i].fail].siz+=prt[i].siz;
}
int main() {
	// 关于优先级的问题:0是空串,1的长度是-1,所以0的优先级比1高 
	num=lst=1,prt[1].len=-1,prt[0].fail=prt[1].fail=1;
	scanf("%d",&len);
	scanf("%s",s+1);
	for(n=1;n<=len;n++) extand(s[n]-'a'); 
	calc();
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值