[SCOI2016] 背单词 (Trie树)

 $pdf$ solution

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#define ll long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=510001;
vector<int> ve[MAXN];
struct node{
    int u,v,nex;
}x[MAXN<<2];
int head[MAXN],cnt;
void add(int u,int v){
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int ch[MAXN][28],bo[MAXN],siz[MAXN],tot=1;
struct Trie{
    void init(){memset(ch,-1,sizeof(ch));}
    void insert(char *s){
        int len=strlen(s);
        int u=1;
        for(int i=len-1;i>=0;i--){
            int c=s[i]-'a';
            if(ch[u][c]==-1) {
                ch[u][c]=++tot;
                add(u,ch[u][c]);
            }
            u=ch[u][c];
        }
        bo[u]++;
        return;
    }
}trie;
void build(int u,int spe){
    if(bo[u]) ve[spe].push_back(u),spe=u;
    for(int i=head[u];i!=-1;i=x[i].nex) build(x[i].v,spe);
}
int n;
void init_siz(int u){
    siz[u]=1;
    int Siz=ve[u].size();
    for(int i=0;i<Siz;i++){
        init_siz(ve[u][i]);
        siz[u]+=siz[ve[u][i]];
    }return;
}ll Tot,ans;
bool cmp(int xx,int yy){
    return siz[xx]<siz[yy];
}
void query(int u,int time){
//    printf("u:%d time:%d\n",u,time);
    int p=++Tot;
    ans+=(ll)p-time;
    sort(ve[u].begin(),ve[u].end(),cmp);
    int siz=ve[u].size();
    for(int i=0;i<siz;i++) query(ve[u][i],p);
    return;
}
char str[MAXN],str1[MAXN];
signed main(){
//    freopen("word.in","r",stdin);
    memset(head,-1,sizeof(head));
    trie.init();
    n=read();
    for(int i=1;i<=n;i++){
        scanf("%s",str);
        trie.insert(str);
    }
    build(1,1);
    init_siz(1);
    query(1,1);
    printf("%lld\n",ans);
}/*
2
aa
aaa
*/
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/10538735.html