1. 程式人生 > >【CF873F】Forbidden Indices 後綴自動機

【CF873F】Forbidden Indices 後綴自動機

出現 scan char ext scanf space brush 長度 最大

【CF873F】Forbidden Indices

題意:給你一個串s,其中一些位置是危險的。定義一個子串的出現次數為:它的所有出現位置中,不是危險位置的個數。求s的所有子串中,長度*出現次數的最大值。

|S|<=200000

題解:板子題啊,沿著pre樹統計一下子樹權值和,然後用mx*權值和更新答案就好了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=400010;
int n,tot,last;
long long ans;
char S[maxn],T[maxn];
int ch[maxn][26],pre[maxn],mx[maxn],r[maxn],st[maxn],tb[maxn];
inline void extend(int x)
{
	int p=last,np=++tot;
	mx[np]=mx[p]+1,last=np;
	for(;p&&!ch[p][x];p=pre[p])	ch[p][x]=np;
	if(!p)	pre[np]=1;
	else
	{
		int q=ch[p][x];
		if(mx[q]==mx[p]+1)	pre[np]=q;
		else
		{
			int nq=++tot;
			mx[nq]=mx[p]+1,pre[nq]=pre[q],pre[np]=pre[q]=nq;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			for(;p&&ch[p][x]==q;p=pre[p])	ch[p][x]=nq;
		}
	}
}
int main()
{
	scanf("%d%s%s",&n,S,T);
	int i;
	last=tot=1;
	for(i=0;i<n;i++)	extend(S[i]-‘a‘),r[last]=‘1‘-T[i];
	for(i=1;i<=tot;i++)	st[mx[i]]++;
	for(i=1;i<=tot;i++)	st[i]+=st[i-1];
	for(i=tot;i>=1;i--)	tb[st[mx[i]]--]=i;
	for(i=tot;i>=1;i--)	r[pre[tb[i]]]+=r[tb[i]];
	for(i=1;i<=tot;i++)	ans=max(ans,1ll*r[i]*mx[i]);
	printf("%I64d",ans);
	return 0;
}

【CF873F】Forbidden Indices 後綴自動機