zoukankan      html  css  js  c++  java
  • P3294 [SCOI2016]背单词

    P3294 [SCOI2016]背单词

    Trie+贪心

    倒插进树+取出重建+子树处理+贪心遍历

    倒插进树:把后缀转化为前缀,所以把字符串倒着插进Trie中

    取出重建:重新建立一棵以单词为节点的树,如果存在包含(前缀)关系就连边

    子树处理:处理出每棵树的大小用于贪心

    贪心遍历:遍历整棵新树,累加答案

    关于贪心:每次找到最小的子树统计答案

    end.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    struct data{
        int nxt[27],end;
        data(){memset(nxt,0,sizeof(nxt)); end=0;}
    }a[510003];
    vector <int> g[100002]; //存边
    int n,cnt,len,siz[100002];
    long long f[100002];
    char q[510003];
    inline bool cmp(const int &A,const int &B) {return siz[A]<siz[B];}
    inline void read_q(){
        char c=getchar(); len=0;
        while(c<'a'||c>'z') c=getchar();
        while('a'<=c&&c<='z') q[len++]=c,c=getchar();
    }
    inline void insert_(int id){ //建树
        read_q();
        int u=0;
        for(int i=len-1;i>=0;--i){
            int p=q[i]-'a';
            if(!a[u].nxt[p]) a[u].nxt[p]=++cnt;
            u=a[u].nxt[p];
        }a[u].end=id; //编号代替单词
    }
    inline void rebuild(int x,int p){ //重新建树
        if(a[x].end) g[p].push_back(a[x].end); //存在前缀关系连边
        for(int i=0;i<26;++i){
            int to=a[x].nxt[i];
            if(!to) continue;
            rebuild(to,a[x].end ? a[x].end:p);
        }
    }
    inline void dfs1(int x){
        siz[x]=1;
        for(int i=0;i<g[x].size();++i){
            int to=g[x][i];
            dfs1(to);
            siz[x]+=siz[to];
        }
        sort(g[x].begin(),g[x].end(),cmp); //按子树从小到大排序
    }
    inline void dfs2(int x){
        f[x]=x? 1:0;
        long long tmp=0;
        for(int i=0;i<g[x].size();++i){
            int to=g[x][i];
            dfs2(to);
            f[x]+=f[to]+tmp; //贪心累加答案
            tmp+=siz[to];
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i) insert_(i);
        rebuild(0,0);
        dfs1(0);
        dfs2(0);
        printf("%lld",f[0]);
        return 0;
    }
  • 相关阅读:
    位运算
    LeetCode(230):二叉树中的第K小元素
    LeetCode(69):二分法求平方根
    TCP如何保证传输可靠性
    2种方法(递归+BFS)求二叉树的最小/最大深度
    自动生成Mapper文件(基于Mybatis Maven插件)
    Git的使用
    Java关键字及其作用详解
    Vagrant安装Centos/7
    java servlet 几种页面跳转的方法及传值
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9614349.html
Copyright © 2011-2022 走看看