[SCOI2016] 背单词 (Trie树)
Posted si-rui-yang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 ",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 ",ans); }/* 2 aa aaa */
以上是关于[SCOI2016] 背单词 (Trie树)的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj4567][Scoi2016][背单词] (贪心+trie树)