背单词(Bzoj4567)

试题描述
Lweb 面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」。这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,然后凤老师告诉 Lweb ,我知道你要学习的单词总共有 n个,现在我们从上往下完成计划表,对于一个序号为 x 的单词(序号 1…x−1 都已经被填入):
如果存在一个单词是它的后缀,并且当前没有被填入表内,那他需要吃 n×n颗泡椒才能学会;
当它的所有后缀都被填入表内的情况下,如果在 1…x−1的位置上的单词都不是它的后缀,那么你吃 x 颗泡椒就能记住它;
当它的所有后缀都被填入表内的情况下,如果 1…x−1 的位置上存在是它后缀的单词,所有是它后缀的单词中,序号最大为 y ,那么你只要吃 x−y  颗泡椒就能把它记住。
Lweb 是一个吃到辣辣的东西会暴走的奇怪小朋友,所以请你帮助 Lweb,寻找一种最优的填写单词方案,使得他记住这 n 个单词的情况下,吃最少的泡椒。
输入
输入一个整数 n ,表示 Lweb 要学习的单词数。接下来 n  行,每行有一个单词(由小写字母构成,且保证任意单词两两互不相同,1≤n≤100000 ,所有字符的长度总和 1≤∣len∣≤510000 )
输出
Lweb 吃的最少泡椒数。
输入示例
2
a
ba
输出示例
2
其他说明
数据范围与提示
1≤n≤100000 ,所有字符的长度总和 1≤∣len∣≤510000 

这道题考什么呢?

是读题啦!

写了两天的代码,发现结果错误,然后看题解,发现我理解错了

我这人平时是很温和的,也不轻易D人,然而这次有点忍不了

TM是什么JB玩意儿,出题人教你语文的体育老师还健在吗

别的题解D的都比我好,大家有兴趣就可以去看

首先是trie树无疑了,但是我们发现只与后缀有关

所以要反向存

然后就是一波贪心

然后就是这题最好别做

还有就是要卡int

下面给出代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
inline long long rd(){
    long long x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
inline void write(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}
long long n;
long long trie[510006][50];
long long total=1;
long long len;
long long vis[510006];
long long head[510006],nxt[510006],to[510006];
long long tot=0;
void add(long long x,long long y){
    tot++;
    to[tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
    return ;
}
char x[510006];
void pre(long long v){
    long long c=1;
    for(long long i=len;i>=1;i--){
        long long s=x[i]-'a';
        if(!trie[c][s]) trie[c][s]=++total;
        c=trie[c][s];
    }
    vis[c]=v;
    return ;
}
void dfs(long long x,long long y){
    if(vis[x]) add(y,vis[x]),y=vis[x];
    for(long long i=0;i<=30;i++) if(trie[x][i]) dfs(trie[x][i],y);
    return ;
}
struct node{
    long long dis,v;
}s[510006];
long long num[510006];
long long ans=0;
bool cmp(node x,node y){
    return x.dis<y.dis;
}
long long f[110006];
void dfss(long long x){
    num[x]=1;
    for(long long e=head[x];e;e=nxt[e]){
        dfss(to[e]);
        num[x]+=num[to[e]];
    }
    long long cnt=0;
    for(long long e=head[x];e;e=nxt[e]){
        s[++cnt].dis=num[to[e]];
        s[cnt].v=to[e];
    }
    sort(s+1,s+cnt+1,cmp);
    long long sum=1;
    for(long long i=1;i<=cnt;i++){
        f[x]+=f[s[i].v]+sum;
        sum+=s[i].dis;
    }
    return ;
}
int main(){
    n=rd();
    for(long long i=1;i<=n;i++){
        scanf("%s",x+1);
        len=strlen(x+1);
        pre(i);
    }
    dfs(1,0);
    dfss(0);
    printf("%lld",f[0]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WWHHTT/p/9715627.html
今日推荐