Prefix of Suffixes

watersail / 2024-09-26 / 原文

  • 为什么求Z函数的过程又被称为【扩展KMP】呢?因为KMP算法是可以求出哪些后缀能与前缀完全匹配的,而Z函数则对于那些不能完全匹配的后缀,求出了最大的匹配长度
  • 现在你已经将问题转化为:在未被标记的后缀中,快速锁定当前新增的字符会使得哪些后缀失配
  • “未被标记”太抽象了,回溯这个条件——在【当前能与前缀完全匹配的后缀中】,这不就是【KMP】求的东西嘛!
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int s[300005],a[300005],b[300005];
int nx[300005],fa[300005];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin>>n;
	long long sum=0,ans=0;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i]>>a[i]>>b[i];
		s[i]=(s[i]+ans)%n;
		if(fa[i-1]&&s[fa[i-1]+1]==s[i])
		{
			fa[i-1]=fa[fa[i-1]];//要等s[i]出现以后才能判断
		}
		sum+=b[i];
		if(i==1)
		{
			nx[1]=0;
			fa[1]=0;
		}
		else
		{
			int j=nx[i-1];
			while(j&&s[j+1]!=s[i])
			{
				j=nx[j];
			}
			if(s[j+1]==s[i])
			{
				j++;
			}
			nx[i]=j;
			fa[i]=j;
		}
		int j=nx[i-1];
		while(1)
		{
			if(s[j+1]!=s[i])
			{
				int id=i-j;
				sum-=b[id];
				if(j==0)
				{
					break;
				}
				j=nx[j];
			}
			else
			{
				if(j==0)
				{
					break;
				}
				j=fa[j];
			}
		}
		ans=ans+sum*a[i];
		cout<<ans<<"\n";
	}
	return 0;
}