ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

4.22 省选模拟赛 三元组 manacher 回文自动机

2020-04-22 16:03:22  阅读:223  来源: 互联网

标签:cnt 省选 manacher 三元组 ww int MAXN fail 回文


avatar
avatar

容易发现可以枚举j 那么只需要计算出 l~j这段是回文串的l的和 以及j+1~r这段是回文串的r的和。

可以manacher 之后想要求出以j为右端点的回文串左端点的和 这个东西我们通过某个点为中心的最长回文子串来做出。

容易发现是一个类似于等差数列的东西的 可以上线段树 不过没有在线询问啥的 可以差分。

由于公差相同 所以一些标记是可以合并的 不过需要分奇偶进行分类讨论 注意差分的位置也不要错了。。

实际上要差分两边 维护两个数组一个维护和的差分 一个维护等差数列的差的差分即可。

这样复杂度为O(n)。

但是这样过于麻烦了。

考虑回文自动机 可以发现建立出来之后 可以直接求出以某个端点为左端点的回文串的个数以及回文串的长度和。

这样求出左端点的和就很容易了。同理右端点再从后往前建一个即可。

时间复杂度O(n) 不过由于是多组数据 每次需要清空 所以多一个log=26的常数。勉强能过。

ps:回文自动机很容易忘 但是 建立时可以依靠几个关键点来建立:奇偶根不能忘 偶根fail指向奇根 奇根的长度为-1.

先判断以当前点之前有没有出现过回文串 然后 没有的话 就可以建点了 然后先找fail再把点安上去 防止自己找到自己。然后更新一下信息即可。

注意 这样做 我们可以非常显然的得到一个推论:一个长度为n的字符串的本质不同的回文串最多有n种 这个还是挺妙的。

const int MAXN=1000010;
int T,n;
int s[MAXN];char a[MAXN];
struct wy//PAM 咋写啊啊啊
{
	int cnt,last,c[MAXN],cc[MAXN];
	int fail[MAXN],len[MAXN];
	int t[MAXN][26],pos[MAXN];
	inline void cle()
	{
		cnt=1;last=1;
		memset(t[0],0,sizeof(t[0]));
		memset(t[1],0,sizeof(t[1]));
		len[1]=-1;fail[0]=1;
		len[0]=0;fail[1]=1;
	}
	inline int get_num()
	{
		++cnt;len[cnt]=fail[cnt]=0;
		memset(t[cnt],0,sizeof(t[cnt]));
		return cnt;
	}
	inline int get_fail(int x,int w)
	{
		while(s[w-len[x]-1]!=s[w])x=fail[x];
		return x;
	}
	inline void insert(int x)
	{
		int w=get_fail(last,x);
		if(!t[w][s[x]])
		{
			int ww=get_num();//创建新节点.
			fail[ww]=t[get_fail(fail[w],x)][s[x]];
			t[w][s[x]]=ww;c[ww]=c[fail[ww]]+1;
			len[ww]=len[w]+2;cc[ww]=(cc[fail[ww]]+len[ww])%mod;
		}
		last=t[w][s[x]];
	}
}A,B;
int main()
{
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	gt(T);
	while(T--)
	{
		int ans=0;
		gc(a);n=strlen(a+1);A.cle();B.cle();
		s[0]=mod;rep(1,n,i)s[i]=a[i]-'a',A.insert(i),A.pos[i]=A.last;
		s[0]=mod;fep(n,1,i)s[n-i+1]=a[i]-'a',B.insert(n-i+1),B.pos[i]=B.last;
		//rep(1,n,i)cout<<A.len[A.pos[i]]<<endl;
		//rep(1,n,i)cout<<B.cc[B.pos[i]]<<endl;
		rep(1,n-1,i)
		{
			//计算左边i 右边i+1
			int cnt1=(ll)(A.c[A.pos[i]]*(i+1)-A.cc[A.pos[i]])%mod;
			int cnt2=((ll)B.c[B.pos[i+1]]*i+B.cc[B.pos[i+1]])%mod;
			ans=(ans+(ll)cnt1*cnt2)%mod;
		}
		put((ans+mod)%mod);
	}
	return 0;
}

标签:cnt,省选,manacher,三元组,ww,int,MAXN,fail,回文
来源: https://www.cnblogs.com/chdy/p/12752682.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有