您的位置:首页 > 其它

4567: [Scoi2016]背单词

2017-07-31 10:41 330 查看
逆序插入字典树,dfs时每次先搜单词数最少的子树。

然而这是错的。

反例输入:

7

aa

aba

abb

ba

bb

bc

bd

然后你就挂了。

因此必须缩点,dfs时每次找size最小的子树。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define G getchar()
#define LL long long
#define pii pair<int,int>
#define mkp make_pair
#define X first
#define Y second
int c[510005][26],n,id,sz[510005],cnt;LL ans;
char s[510005];bool dg[510005];
vector<int>v[510005];
void ins(){
int x=1,ch,i;
per(i,strlen(s)-1,0){
int &y=c[x][ch=s[i]-'a'];
if(!y)y=id++;
x=y;
}
dg[x]=1;
}
void DFS0(int x,int an){
int i,y;
if(dg[x]){
v[an].push_back(x);an=x;
}
rep(i,0,25)if(y=c[x][i])
DFS0(y,an);
}
void DFS1(int x){
sz[x]=1;
vector<int>::iterator ii;
for(ii=v[x].begin();ii!=v[x].end();++ii){
DFS1(*ii);sz[x]+=sz[*ii];
}
}
bool cmp(int x,int y){
return sz[x]<sz[y];
}
void DFS2(int x,int an){
if(x>1){ans+=++cnt-an;an=cnt;}
sort(v[x].begin(),v[x].end(),cmp);
vector<int>::iterator ii;
for(ii=v[x].begin();ii!=v[x].end();++ii)
DFS2(*ii,an);
}
int main(){
//	freopen("r.in","r",stdin);
//	freopen("w.out","w",stdout);
int i;
scanf("%d",&n);id=2;
while(n--){
scanf("%s",s);
ins();
}
DFS0(1,1);DFS1(1);DFS2(1,0);
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: