• Gitignore 2020 上海icpc区域赛


    Gitignore 2020 上海icpc区域赛

    题目大意:

    给你n个可以删除的文件路径,m个不能删除的文件路径,问最后删去所有可以删除的文件路径的最短的次数是多少?

    文件路径有五个限制:

    • 文件路径不为空,且最后一定是一个文件,即不能以/ 结尾
    • 目录不能以 / 开头
    • 文件名和目录不为空,即不能有连续的 /
    • 所有的文件路径一定互不相同
    • 一个目录中不会出现子目录和最后的文件名相同

    题解:

    这个画个图其实就很明白了,最后一定会是一棵树,但是这棵树因为文件名和目录名可能相同,所以不能直接用名字来建树,我使用的是以字典树的方式来建树,这样可以消除文件名和目录名可能相同的影响,建好树之后,问题就变成,一棵树最少删去多少个节点,使得最后树上的节点都是我们需要的。

    代码还是有点难码,因为要这里会有两个映射,一个是字符串到数字,一个是数字到树节点的映射。

    要注意区分!

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e3+10;
    typedef pair<int,int>pii;
    map<pii,int>trie;
    map<string,int>mp;
    vector<int>G[maxn];
    char s[maxn];
    int now,tot,flag[maxn];
    void init(){
        now = tot = 0;
        mp.clear(),trie.clear();
        for(int i=0;i<=1005;i++) flag[i] = false,G[i].clear();
    }
    void insert(int len){
        int u = 0;
        string str = "";
        for(int i=1;i<=len;i++){
            if(s[i]=='/'){
                if(!mp[str]) mp[str] = ++now;
                int v = mp[str];
                if(!trie[pii(u,v)]) trie[pii(u,v)] = ++tot,G[u].push_back(tot);
                u = trie[pii(u,v)],str = "";
            }
            else str += s[i];
        }
    }
    void update(int len){
        int u = 0;
        string str = "";
        for(int i=1;i<=len;i++){
            if(s[i]=='/'){
                int v = mp[str];
                if(!v||!trie[pii(u,v)]) return ;
                u = trie[pii(u,v)];
                str = "",flag[u] = true;
            }
            else str += s[i];
        }
    }
    int dfs(int u){
        int ans = 0;
        if(!flag[u]) return 1;
        for(int i=0;i<G[u].size();i++){
            int v = G[u][i];
    //        printf("u = %d v = %d
    ",u,v);
            ans+=dfs(v);
        }
        return ans;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            init();
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++){
                scanf("%s",s+1);
                int len = strlen(s+1);
                s[len+1] = '/',insert(len+1);
            }
            flag[0] = true;
            for(int i=1;i<=m;i++){
                scanf("%s",s+1);
                int len = strlen(s+1);
                s[len+1] = '/',update(len+1);
            }
            int ans = dfs(0);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    Linux 内核优化
    Myeclipse7.5 下载 安装 注冊 注冊码 100%成功
    Nmap命令的29个实用范例
    运维工程师必会的109个Linux命令
    linux下维护服务器之常用命令
    黑客工具软件大全100套
    Sysstat性能监控工具包中20个实用命令
    100个linux常用命令
    28 个 Unix/Linux 的命令行神器
    linux命令合集
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14291775.html
Copyright © 2020-2023  润新知