zoukankan      html  css  js  c++  java
  • 背单词(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;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    SQL Server 中关于EXCEPT和INTERSECT的用法
    SQL SERVER 索引中聚集索引分析和Transact-SQL语句优化
    DATEDIFF() 返回2个日期之间的间隔
    CharIndex()
    poj1470 Closest Common Ancestors [ 离线LCA tarjan ]
    2014 蓝桥杯 预赛 c/c++ 本科B组 第九题:地宫取宝(12') [ dp ]
    hdu 2438 Turn the corner [ 三分 ]
    poj 3295 Tautology [ 栈 ]
    hdu 4923 Room and Moor [ 找规律 + 单调栈 ]
    1597: [Usaco2008 Mar]土地购买 [ dp+斜率优化 ] 未完
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9715627.html
Copyright © 2011-2022 走看看