Day2T2 分配笔名//CF566A

首先建一个Trie,考虑贪心选深层节点合并。

#include
#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<endl;
}

如果要求输出方案呢?

即是CF566A

 考虑用一个Vector来维护每个点结尾的ID,也没什么差吧

#include
#pragma GCC optimize("O2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("O3")
#include
#include
#include
#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];
vectorint,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;j0].size();++j)cnt[u][0].push_back(cnt[v][0][j]);//记录子节点的id
            for(register int j=0;j1].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;ii){
         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;ii){
         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倍

你可能感兴趣的:(Day2T2 分配笔名//CF566A)