Day2T2 分配笔名//CF566A
首先建一个Trie,考虑贪心选深层节点合并。
#include<bits/stdc++.h> #define fr(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int N=2e6+5; int n,p=1; int ch[N][26],cnt[N][2]; long long ans; inline void insert(char *a,int v){//普通插入 int u=1; fr(i,0,strlen(a)-1){ int c=a[i]-'a'; if(!ch[u][c])ch[u][c]=++p; u=ch[u][c]; } ++cnt[u][v];//当前节点结尾的单词+1 } inline void dfs(int u,int dep){ fr(i,0,25){ if(ch[u][i])dfs(ch[u][i],dep+1);//递归到深层子节点,让能合并的先合并,得到的就是更优解 cnt[u][0]+=cnt[ch[u][i]][0];//加上子节点剩余的字符串 cnt[u][1]+=cnt[ch[u][i]][1]; } int k=min(cnt[u][0],cnt[u][1]);//计算公共部分 ans+=1ll*k*dep;//累计次数 cnt[u][0]-=k;cnt[u][1]-=k;//消除已匹配的数量 } char a[N]; int main(){ scanf("%d",&n); fr(i,1,n)cin>>a,insert(a,0); fr(i,1,n)cin>>a,insert(a,1); dfs(1,0); cout<<ans<<endl; }
如果要求输出方案呢?
即是CF566A
考虑用一个Vector来维护每个点结尾的ID,也没什么差吧
#include<vector> #pragma GCC optimize("O2") #pragma GCC optimize("Ofast") #pragma GCC optimize("O3") #include<cstring> #include<iostream> #include<cstdio> #define fr(i,a,b) for(register int i=a;i<=b;++i) #define rf(i,a,b) for(register int i=a;i>=b;--i) using namespace std; const int N=1e6+5; int n,p=1,pa[N]; int ch[N][26]; vector<int> cnt[N][2]; vector<pair<int,int> > as; long long ans; inline void dfs(int u,int dep){ fr(i,0,25){ int v=ch[u][i]; if(v){ dfs(v,dep+1); for(register int j=0;j<cnt[v][0].size();++j)cnt[u][0].push_back(cnt[v][0][j]);//记录子节点的id for(register int j=0;j<cnt[v][1].size();++j)cnt[u][1].push_back(cnt[v][1][j]); } } ans+=min(cnt[u][0].size(),cnt[u][1].size())*dep;//先把共同的匹配 for(register int i=min(cnt[u][0].size(),cnt[u][1].size())-1;i>-1;--i){ as.push_back({cnt[u][0][cnt[u][0].size()-1],cnt[u][1][cnt[u][1].size()-1]});//记录方案 cnt[u][0].pop_back();cnt[u][1].pop_back();//删除已匹配的数 } } string a; int main(){ cin>>n; fr(id,1,n){ cin>>a; int u=1; for(register int i=0;i<a.size();++i){ int c=a[i]-'a'; if(ch[u][c]==0)ch[u][c]=++p; u=ch[u][c]; } cnt[u][0].push_back(id); } fr(id,1,n){ cin>>a; int u=1; for(int i=0;i<a.size();++i){ int c=a[i]-'a'; if(!ch[u][c])ch[u][c]=++p; u=ch[u][c]; } cnt[u][1].push_back(id);//记录 } dfs(1,0); printf("%d\n",ans); fr(i,0,n-1)printf("%d %d\n",as[i].first,as[i].second); }
还有,string和char差这么多,快了N倍
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步