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;
}
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
weilx12343 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
Smileyqp沛沛3 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
m0_547486663 天前
《数据结构教程》全套 PPT课件2026
数据结构
C语言小火车3 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
吞下星星的少年·-·3 天前
C++ 萌新语法入门篇
c++·算法比赛