P9831 [ICPC2020 Shanghai R] Gitignore

P9831 [ICPC2020 Shanghai R] Gitignore - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)


只看题意翻译这道题是做不出来的,还要去看英文里面的规定(这里就不放英文了),主要问题是不要公用子文件夹。

例如:

1 / a / 2

2 / a / 3

文件夹a有2个,而非1个。

仔细阅读理解之后就会发现我们需要的结构是如下图所示的目录类型的树

比较容易想到的就是给每个文件夹一个独一无二文件夹空间。

例如下图

文件夹1的文件空间为1,文件空间里面还有一个文件夹1,由于此处内部的文件夹1没有内容,所以不需要给他赋值空间,如果有需要,可以加上空间。

大概能理解这个思想之后直接看代码。

AC代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int idx,T,ans;
map<string,int>f;//第一列文件初始化空间
bool a[10001];//空间是否可以被直接删除
bool vis[10001];
           //文件名 文件空间
vector<pair<string,int>>e[10001];//文件空间i 拥有的文件e[i]
//此处拥有的文件也有可能拥有文件,所以保留<文件名,文件空间>
string s,t;

void push_down(int x){
    if(vis[x])return;
    vis[x]=true;
    for(auto i:e[x])push_down(i.second);
}
void dfs(int x){
    if(vis[x])return;
    vis[x]=true;
    if(a[x]){//当前文件夹能删除,直接删除
        vis[x]=false;
        ans++;
        push_down(x);//标记此文件夹拥有的文件均不用再访问了.
        return;
    }
    for(auto i:e[x])dfs(i.second);//访问当前文件夹所有内容
}

void solve(){
    f.clear();
    ans=0;
    for(int i=1;i<=10000;++i){
        a[i]=vis[i]=false;
        e[i].clear();
    }
    
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n+m;++i){
        cin>>s,s+='/',t="";
        for(int j=0,k=0,now;j<(int)s.length();++j){
            if(s[j]=='/'){//找到"/" 说明一个文件名输入完毕
                if(k==0){//若k=0 说明是一级文件夹,最前面的均分配一个f[t]空间
                    if(!f[t])f[t]=++idx;//是第一次出现,分配空间idx,此处空间idx会一直递增,保证空间号不同
                    now=f[t];
                    k=1;
                }else{//不是一级文件夹,此处需要用到now来递归空间号
                    bool flag=true;
                    for(auto k:e[now]){//遍历前一次空间号now的内容
                        if(k.first==t){//如果文件t已经存在
                            flag=false;
                            now=k.second;//获取文件t的空间号,更新now,准备下一次使用
                        }
                    }
                    if(flag){//如果文件t不存在
                        e[now].push_back({t,++idx});//手动加入,并且赋予新的空间号
                        now=idx;//更新now,准备下一次使用
                    }
                }
                if(i<=n)a[now]=true;//前n个路径全都需要删除
                else a[now]=false;//后m个不需要删除
                t="";
            }else t+=s[j];
        }
    }
    for(auto i:f){//第一列开始读取文件夹
        if(a[i.second])ans++;//如果一级文件夹就需要删除,那就不需要再往下了
        else dfs(i.second);//深搜.
    }
    cout<<ans<<endl;
}

int main(){
    cin>>T;
    while(T--)solve();
    return 0;
}
相关推荐
此生只爱蛋15 分钟前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
blammmp22 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧35 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
昂子的博客44 分钟前
基础数据结构——队列(链表实现)
数据结构
咕咕吖1 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
九圣残炎1 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
丫头,冲鸭!!!2 小时前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
Re.不晚2 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
ULTRA??2 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++