在ZIP归档文件中,保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时,可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。
输入格式:
输入首先给出正整数N(≤10^4),表示ZIP归档文件中的文件和目录的数量。随后N行,每行有如下格式的文件或目录的相对路径和名称(每行不超过260个字符):
路径和名称中的字符仅包括英文字母(区分大小写);
符号“\”仅作为路径分隔符出现;
目录以符号“\”结束;
不存在重复的输入项目;
整个输入大小不超过2MB。
输出格式:
假设所有的路径都相对于root目录。从root目录开始,在输出时每个目录首先输出自己的名字,然后以字 典 序输出所有子目录,然后以字典序输出所有文件。注意,在输出时,应根据目录的相对关系使用空格进行缩 进,每级目录或文件比上一级多缩进2个空格。
输入样例:
7
b
c\
ab\cd
a\bc
ab\d
a\d\a
a\d\z\
输出样例:
root
a
d
z
a
bc
ab
cd
d
c
b
坑点
目录(后面有'\')
和文件(后面没有'\')
文件夹
排在文件
的前面
笔记一 : 重写map比较器
struct cmp { //重写string比较让文件夹排在文件前面
// 即 'xxx/' < 'xxx'
bool operator() (const string& a, const string& b) const {
if(a.back() == '\\' && b.back() != '\\') return true;
if(a.back() != '\\' && b.back() == '\\') return false;
return a < b;
}
} ;
map要这样使用
map<string, Node*, cmp> chls;
文件或文件夹结构体
struct Node {
bool dir; //标记是否是文件夹
string name; //文件名
map<string, Node*, cmp> chls; //子文件或子目录
//以下是一些重写的比较函数
bool operator < (const Node& no) const {
if(name.length() > no.name.length()) return false;
return name < no.name;
}
bool operator = (const Node& no) const {
return name == no.name;
}
bool operator < (const string& no) const {
if(name.length() > no.length()) return false;
return name < no;
}
bool operator = (const string& nostr) const {
return name == nostr;
}
} root = { true, "root", { } };
完整代码如下
#define debug
#ifdef debug
#include
#include "/home/majiao/mb.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXN ((int)1e5+7)
#define ll long long
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)
using namespace std;
#ifdef debug
#define show(x...) \
do { \
cout << "\033[31;1m " << #x << " -> "; \
err(x); \
} while (0)
#else
#define show(x...)
#endif
void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
namespace FastIO {
char print_f[105];
void read() { }
void print() { putchar('\n'); }
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth) {
x = 0;
char ch = getchar();
ll f = 1;
while (!isdigit(ch)) {
if (ch == '-') f *= -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getchar();
}
x *= f;
read(oth...);
}
template <typename T>
inline void put(T x) {
if(x==0) { putchar('0'); putchar('\n'); return; }
if(x<0) { putchar('-'); x = -x; }
int num=0;
char ch[128];
while(x) ch[++num] = x % 10 + '0', x /= 10;
while(num) putchar(ch[num--]);
putchar('\n');
}
}; // namespace FastIO
using FastIO::read;
using FastIO::put;
int n, m, Q, K;
char buf[512];
struct cmp {
bool operator() (const string& a, const string& b) const {
if(a.back() == '\\' && b.back() != '\\') return true;
if(a.back() != '\\' && b.back() == '\\') return false;
return a < b;
}
} ;
struct Node {
bool dir; //标记是否是文件夹
string name; //文件名
map<string, Node*, cmp> chls; //子文件或子目录
//以下是一些重写的比较函数
bool operator < (const Node& no) const {
if(name.length() > no.name.length()) return false;
return name < no.name;
}
bool operator = (const Node& no) const {
return name == no.name;
}
bool operator < (const string& no) const {
if(name.length() > no.length()) return false;
return name < no;
}
bool operator = (const string& nostr) const {
return name == nostr;
}
} root = { true, "root", { } };
void insert(Node* now, char* s, int timer) { //递归插入目录树
string tmp;
//从字符串中剪裁出前面的文件夹
//即从 'abc/def/gh' 里剪裁出 'abc/'
for(; *s; ) {
if((*s) == '\\') {
s ++;
tmp.push_back('\\');
break;
} else
tmp.push_back(*s++);
}
if(tmp.empty()) return ;
#if 0
for(int i=0; i<timer; i++)
putchar(' '), putchar(' ');
printf("%s\n", tmp.data());
#endif
if(now->chls.count(tmp)) { //如果在当前节点里已经有子目录tmp了 就接着递归
Node*& tnode = now->chls[tmp];
insert(tnode, s, timer+1);
} else { //如果当前节点没有子目录tmp就创建 并接着递归
Node* node = new Node();
node->name = tmp;
now->chls[tmp] = node;
insert(node, s, timer+1);
}
}
void dfs(Node& now, int timer) { //dfs打印即可
for(int i=0; i<timer; i++)
putchar(' '), putchar(' ');
if(now.name.back() == '\\') now.name.pop_back();
printf("%s\n", now.name.data());
for(auto it = now.chls.begin(); it != now.chls.end(); it ++)
dfs(*it->second, timer+1);
}
signed main() {
#ifdef debug
freopen("test", "r", stdin);
// freopen("out_main", "w", stdout);
clock_t stime = clock();
#endif
read(n);
for(int i=1; i<=n; i++) {
scanf("%s ", buf);
insert(&root, buf, 0);
}
auto it = root.chls.begin();
while(it != root.chls.end()) {
// show(it->first, it->second->name);
it ++;
}
dfs(root, 0);
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}