题解:AT_abc353_e [ABC353E] Yet Another Sigma Problem

字典树模板题。

Code

先贴上字典树板子的代码。

#include<bits/stdc++.h>
using namespace std;
int t,n,q,tree[3000010][71],cnt[3000010],c;
char s[3000010];
int num(char x){
	if(x>='A'&&x<='Z')return x-'A';
	if(x>='a'&&x<='z')return x-'a'+26;
	if(x>='0'&&x<='9')return x-'0'+52;
}
void insert(char str[]){
	int now=0,len=strlen(str);
	for(int i=0;i<len;i++){
		int numer=num(str[i]);
		if(!tree[now][numer])tree[now][numer]=++c;
		now=tree[now][numer];
		cnt[now]++;
	}
}
int finding(char str[]){
	int now=0,len=strlen(str);
	for(int i=0;i<len;i++){
		int numer=num(str[i]);
		if(!tree[now][numer])return 0;
		now=tree[now][numer];
	}
	return cnt[now];
}
int main(){
	cin>>t;
	while(t--){
		for(int i=0;i<=c;i++){
			for(int j=0;j<=70;j++){
				tree[i][j]=0;
			}
		}
		for(int i=0;i<=c;i++)cnt[i]=0;
		c=0;
		cin>>n>>q;
		for(int i=1;i<=n;i++){
			cin>>s;
			insert(s);
		}
		for(int i=1;i<=q;i++){
			cin>>s;
			cout<<finding(s)<<endl;
		}
	}
	return 0;
}

不难发现,我们为了找出有多少个 ss 前缀包含 tt,使用了 cntcnt 数组。

本题其实也差不多。

先附上代码。

#include<bits/stdc++.h>
using namespace std;
int t,n,q,tree[3000010][71],cnt[3000010],c;
char s[3000010];
int num(char x) {
	if(x>='A'&&x<='Z')return x-'A';
	if(x>='a'&&x<='z')return x-'a'+26;
	if(x>='0'&&x<='9')return x-'0'+52;
}
void insert(char str[]) {
	int now=0,len=strlen(str);
	for(int i=0; i<len; i++) {
		int numer=num(str[i]);
		if(!tree[now][numer])tree[now][numer]=++c;
		now=tree[now][numer];
		cnt[now]++;
	}
}
int main() {
	for(int i=0; i<=c; i++) {
		for(int j=0; j<=70; j++) {
			tree[i][j]=0;
		}
	}
	for(int i=0; i<=c; i++)cnt[i]=0;
	c=0;
	cin>>n;
	for(int i=1; i<=n; i++) {
		cin>>s;
		insert(s);
	}
	long long ans=0;
	for(int i=1;i<=c;i++){
		ans+=1ll*cnt[i]*(cnt[i]-1)/2;
	}
	cout<<ans;
	return 0;
}

Idea

对于样例

3
abc ard are

可以建字典树如下:

首先我们对于 a 点,有 33 个字符串共同经过这个点,所以会有 33 组字符串组对这个 a 产生贡献(让答案加 11)。

再看 r 点,有 22 个字符串共同经过这个点,所以会有 11 组字符串组对这个 r 产生贡献。

再手搓几组样例,推广一下结论:有 nn 个字符串共同经过一个点,则就有 n(n1)2\dfrac{n(n-1)}{2} 的字符串组对它产生贡献。

所以我们只需要建树求出 cntcnt 数组(即每个点经过字符串的数量),就可 O(n)\operatorname{O}(n) 地求出答案了。

代码见上。

Tips

  • 本题答案也可能爆 int
  • 如果要实现 int 整数与 int 整数相乘得到 long long 整数,需要乘 1ll(即 long long 类型下的 11),否则系统仍会按照 int 型计算而导致爆 int
posted @   Weslie_qwq  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示