CF1902E Collapsing Strings

CF1902E Collapsing Strings

字典树板题,但是脑子没转过来导致写了很久。

由于字符串的总长度可以接受,所以考虑先建树,然后一个串一串跑,因为字典树单词查询的复杂度是 O(字符串长度),所以复杂度是可以接受的。

由于涉及到翻转,一开始一直以为要建两棵树,结果 MLE 了,看了眼题解之后大彻悟建一棵就够了,把 \(s_i\) 反转一下来查询就可以了。

反思一下,如果对着 \(\sum_{i = 1}^{n}\sum_{j = 1}^{n}C(s_i, s_j)\) 这个式子分析的话,至少可以快40min,自己考虑复杂了,贡献的构成没有想的很清楚。

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 1e6 + 1000;
int ch[N][26], f[N];
int cnt = 0;
string s[N];
void insert(string t){
	int len = t.size(), u = 0;
		F(i, 0, len - 1){
			int v = t[i] - 'a';
			if(!ch[u][v]) ch[u][v] = ++ cnt;
			u = ch[u][v];
		}
		++ f[u];
	}
	void dfs(int u){
		F(i, 0, 25){
			if(ch[u][i]){
				int v = ch[u][i];
				dfs(v);
				f[u] += f[v];
			}
		}
	}
	ll ask(string t){
		int len = t.size(), u = 0;
		ll sum = 0;
		F(i, 0, len - 1){
			int v = t[i] - 'a';
			if(!ch[u][v]) break;
			u = ch[u][v];
			sum += f[u];
//			printf("%c\tf = %d\n", t[i], f[u]); 
		}
		return sum;
	}
int n;
void Main(){
	ll ans = 0, ss = 0;
	cin >> n;
	F(i, 1, n){
		cin >> s[i];
		int l = s[i].size();
		ss += l;
		insert(s[i]);
	}
	dfs(0);
//	F(i, 1, t.cnt){
//		printf("t.f[%d] = %d\t", i, t.f[i]);
//	}
//	printf("\n");	
	F(i, 1, n){

//		ll tmp1 = ask(s[i]);
		reverse(s[i].begin(), s[i].end()); 
		ll tmp = ask(s[i]);
//		printf("i = %d\t tmp = %lld\n", i, tmp);
		ans += tmp;
	}
//	printf("ss = %lld, ans = %lld\n", ss, ans);
	cout << ss * n * 2 - ans * 2 << '\n';
	return ;
}
signed main(){
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int T = 1;
	while(T --) Main();
	return fflush(0), 0;
}
posted @ 2026-09-05 21:53  superl61  阅读(7)  评论(0)    收藏  举报