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;
}
相关推荐
leo__5208 分钟前
基于两步成像算法的聚束模式SAR MATLAB实现
开发语言·算法·matlab
前端小白在前进33 分钟前
力扣刷题:在排序数组中查找元素的第一个和最后一个位置
数据结构·算法·leetcode
咔咔咔的1 小时前
3652. 按策略买卖股票的最佳时机
c++
某林2122 小时前
基于SLAM Toolbox的移动机器人激光建图算法原理与工程实现
stm32·嵌入式硬件·算法·slam
修炼地2 小时前
代码随想录算法训练营第四十三天 | 图论理论基础、深搜理论基础、卡码网98. 所有可达路径、797. 所有可能的路径、广搜理论基础
算法·深度优先·图论
iAkuya2 小时前
(leetcode)力扣100 23反转链表(迭代||递归)
算法·leetcode·链表
剪一朵云爱着2 小时前
PAT 1095 Cars on Campus
算法·pat考试
欧特克_Glodon3 小时前
基于Qt+VTK实现的CT/MR影像浏览工具,支持体渲染及体模型剪裁
c++·qt·vtk·体渲染·裁剪
LBJ辉3 小时前
第 4 章 串
数据结构·考研
MicroTech20253 小时前
激光点云快速配准算法创新突破,MLGO微算法科技发布革命性点云配准算法技术
人工智能·科技·算法