CF1902E. Collapsing Strings-LCP、字典树

link:https://codeforces.com/contest/1902/problem/E

题意:You are given n strings s1,s2,,sn, consisting of lowercase Latin letters. Let |x| be the length of string x. Let a collapse C(a,b) of two strings a and b be the following operation:

  • if a is empty, C(a,b)=b; - if b is empty, C(a,b)=a;
  • if the last letter of a is equal to the first letter of b, then C(a,b)=C(a1,|a|1,b2,|b|), where sl,r is the substring of s from the l-th letter to the r-th one;
  • otherwise, C(a,b)=a+b, i. e. the concatenation of two strings.
    Calculate i=1nj=1n|C(si,sj)|.

|si|106.


C(s,t)=|s|+|t|2×LCP(t,s),其中 s 表示 s 的反串, LCP 表示最长公共前缀。

因此 $$ans=\sum_{i=1}n\sum_{j=1}n |s_i|+|s_j|-2 LCP(s_j,s_i')=2n\cdot\sum_{i=1}n|s_i|-2\sum_{i=1}n\sum_{j=1}^n LCP(s_i',s_j)$$
对于后者,枚举每个 si ,查询其和所有其他串最长公共前缀,将所有串插入到字典树上,做一个子树查询即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int C=26;
int n,tr[N][C+1],tag[N],cnt;
string s[N];
void insert(const string &s){
int len=s.length(),k=0;
for(int i=0;i<len;i++){
int ch=s[i]-'a';
if(!tr[k][ch])tr[k][ch]=++cnt;
k=tr[k][ch];
tag[k]++;
}
}
ll work(const string &s){
int len=s.length(),k=0;
ll ret=0;
for(int i=len-1;i>=0;i--){
int ch=s[i]-'a';
k=tr[k][ch];
if(!k)break;
ret+=tag[k];
}
return ret;
}
int main(){
fastio;
cin>>n;
ll ans=0;
rep(i,1,n){
cin>>s[i];
insert(s[i]);
ans+=(ll)2*n*s[i].length();
}
rep(i,1,n)ans-=2*work(s[i]);
cout<<ans;
return 0;
}
posted @   yoshinow2001  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示