【UNR #6】Border 的第五种求法

【UNR #6】Border 的第五种求法

by AmanoKumiko

Description

给出一个长为\(n\)的字符串\(s\),以及一个长为\(n\)的序列\(f\)

\(m\)次询问,每次给出一个区间\(l,r\)

对于\(s[l\cdots r]\)的所有\(border\),令其出现次数为\(c\),求\(\sum f_c\)

Input

第一行两个数\(n,m\)

Output

\(m\)行每行一个数表示答案

Sample Input

5 4
ababa
1 2 3 4 5
2 3
2 4
1 4
1 5

Sample Output

2
3
3
6

Data Constraint

\(1\le n,m\le 5*10^5\)

Solution

首先这是道板题

我们考虑最暴力的做法

就是计算\(s[l\cdots r]\)和其每个前缀的\(LCS\),看它是不是\(border\)

可以直接做\(DAG\)链剖分

那么找到\(s[l\cdots r]\)\(DAG\)链上对应的点

只要这些点在\(parent\)数上对应的点是\(s[1\cdots r]\)的祖先,就可以对答案贡献

简单数一数就可以了

设路径数为\(S\)

时间复杂度\(O(n\log n+q\log S\log n)\)

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define mo 998244353
#define N 500010
#define LL long long

int mod(int x){return x>=mo?x-mo:x;}

LL ans[N];
int n,m,f[N],pw[N],ipw[N],h[N],ed[N];
char s[N];
struct SAM{
	vector<int>e[N*2];
	LL s1[N*2],s2[N*2]; 
	int ch[N*2][26],link[N*2],len[N*2],sum[N*2],u,rt,tot,lst;
	int nxt[N*2],pre[N*2],son[N*2],rk[N*2],top[N*2],wh[N*2],num;
	int line[N*2],cnt,d[N*2];
	int g[N*2],pos[N*2];
	int *tg[N*2],*tp[N*2];
	int vis[N*2],sz[N*2];
	void build(){
		tot=rt=lst=1;
		F(i,1,n){
			int u=++tot,v=lst,p=s[i]-'a';
			for(;v&&!ch[v][p];v=link[v])ch[v][p]=u,len[u]=max(len[u],len[v]+1);
			if(!v)link[u]=rt;
			else if(len[ch[v][p]]==len[v]+1)link[u]=ch[v][p];
			else{
				int clone=++tot,Old=ch[v][p];
				len[clone]=len[v]+1;
				F(j,0,25)ch[clone][j]=ch[Old][j];
				link[clone]=link[Old];
				link[Old]=link[u]=clone;
				for(;v&&ch[v][p]==Old;v=link[v])ch[v][p]=clone;
			}
			ed[i]=u;
			sum[lst=u]++;
		}
		F(i,1,tot)e[link[i]].push_back(i);
	}
	void DAG(){
		queue<int>q;
		F(i,1,tot) F(j,0,25)if(ch[i][j])d[ch[i][j]]++;
		q.push(1);
		while(!q.empty()){
			int u=q.front();q.pop();
			line[++cnt]=u;
			F(i,0,25)if(ch[u][i]){
				d[ch[u][i]]--;
				if(!d[ch[u][i]])q.push(ch[u][i]);
			}
		}
		Fd(i,cnt,1){
			int u=line[i];s1[u]++;
			sum[link[u]]+=sum[u];
			F(j,0,25)if(ch[u][j]){
				if(s1[ch[u][j]]>s1[nxt[u]])nxt[u]=ch[u][j];
				s1[u]+=s1[ch[u][j]];
			}
		}
		F(i,1,cnt){
			int u=line[i];s2[u]++;
			F(j,0,25)if(ch[u][j]){
				if(s2[u]>s2[pre[ch[u][j]]])pre[ch[u][j]]=u;
				s2[ch[u][j]]+=s2[u];
			}
		}
		F(i,1,tot) F(j,0,25)if(ch[i][j]){
			if(nxt[i]==ch[i][j]&&pre[ch[i][j]]==i)son[i]=ch[i][j],wh[i]=j+1;
		}
		int tmp=0;
		F(i,1,tot){
			int u=line[i];
			if(vis[u])continue;
			int v=u;
			sz[u]=1;rk[u]=++num;top[u]=u;
			while(son[v])sz[u]++,v=son[v],rk[v]=++num,top[v]=u;
			tg[u]=g+tmp;
			tp[u]=pos+tmp;
			v=u;
			int val=0;
			F(j,1,sz[u]){
				vis[v]=1;
				tg[u][j-1]=val;
				tp[u][j-1]=v;
				val=mod(val+1ll*pw[j-1]*wh[v]%mo);
				v=son[v];
			}
			tmp+=sz[u];
		}
	}
}S;
struct BIT{
	LL sum[N*2];
	int lowbit(int x){return -x&x;}
	void modify(int x,int y){for(;x<=S.tot;x+=lowbit(x))sum[x]+=y;}
	LL qur(int x){LL res=0;for(;x;x-=lowbit(x))res+=sum[x];return res;}
}P;
struct node{int l,r,pos;};

vector<node>ask[N*2];

void calc(int u){
	if(u!=1)P.modify(S.rk[u],f[S.sum[u]]);
	for(auto v:S.e[u])calc(v);
	for(auto d:ask[u]){
		ans[d.pos]+=P.qur(d.r)-P.qur(d.l-1);
	}
	if(u!=1)P.modify(S.rk[u],-f[S.sum[u]]);
}

int main(){
	scanf("%d%d",&n,&m);
	scanf("%s",s+1);
	pw[0]=ipw[0]=1;
	F(i,1,n){
		pw[i]=37ll*pw[i-1]%mo;
		ipw[i]=242816194ll*ipw[i-1]%mo;
		h[i]=mod(h[i-1]+1ll*pw[i-1]*(s[i]-'a'+1)%mo);
	}
	F(i,1,n)scanf("%d",&f[i]);
	S.build();
	S.DAG();
	F(i,1,m){
		int l,r;
		scanf("%d%d",&l,&r);
		int u=1,len=0;
		while(len!=r-l+1){
			int up=S.top[u],lu=S.rk[u]-S.rk[up];
			int le=-1,ri=min(r-l+1-len+1,S.sz[up]-lu),mid;
			while(le<ri-1){
				mid=le+ri>>1;
				if(1ll*mod(S.tg[up][lu+mid]-S.tg[up][lu]+mo)*ipw[lu]%mo==
					1ll*mod(h[l+len+mid-1]-h[l+len-1]+mo)*ipw[l+len-1]%mo)le=mid;
				else ri=mid;
			}
			if(le)ask[ed[r]].push_back((node){S.rk[u]+1,S.rk[u]+le,i});
			len+=le;u=S.tp[up][lu+le];
			if(len!=r-l+1){
				u=S.ch[u][s[l+len]-'a'];
				ask[ed[r]].push_back((node){S.rk[u],S.rk[u],i});
				len++;
			}
		}
	}
	calc(1);
	F(i,1,m)printf("%lld\n",ans[i]);
	return 0;
}
posted @ 2022-08-08 15:03  冰雾  阅读(123)  评论(0编辑  收藏  举报