题目链接
题目描述
kkksc03是个非凡的空想家!在短时间内他设想了大量网页,然后总是交给可怜的lzn去实现。
洛谷的网页端,有很多文件夹,文件夹还套着文件夹。
例如:/luogu/application/controller表示根目录下有一个名称为luogu的文件夹,这个文件夹下有一个名称application的文件夹,其中还有名为controller的文件夹。
每个路径的第1个字符总是’/’,且没有两个连续的’/’,最后的字符不是’/’。所有名称仅包含数字和小写字母。
目前根目录是空的。kkksc03想好了很多应该有的文件夹路径名。问题是,需要是使这些文件夹都存在,需要新建几个文件夹呢?
输入输出格式
输入格式:输入文件第1行为一个正整数N。
接下来N行,每行为一个描述路径的字符串,长度均不超过100。
输出格式:输出应包含N行,每行1个正整数,第i行输出若要使第1个路径到第i个路径存在,最少需要新建多少个文件夹。
输入输出样例
说明
数据规模:
对于所有数据,N<=1000。
对于20%数据,有N<=20;
对于50%数据,有N<=200;
对于30%数据,有对于所有路径最多存在两个’/’(包含第1个字符)。
这道题是洛谷上一道模拟题,关于文件夹的,我想应该是和字符串有关就拿来做了。
提供两种思路。一长一短
一、刚开始看这题,想可不可以用取巧的方法,每个文件夹的名字都不一样?然后划分文件夹就可以得出结果了。但马上发现这是不可能的。
再观察题目,因为是和文件夹有关,所以突然想到了树形结构,可以模拟树形结构来统计文件夹的数量。从根节点遍历,查找当前目录可不可以往下走,如果不可以,就新建一个目录,否则往下走。此思路的关键是构建这样一个结构体
struct Node {
string name;
vector<Node*> nexts;
};
然后模拟树形结构,思路简单,代码略长。
#include <iostream>
#include <vector>
using namespace std;
struct Node {
string name;
vector<Node*> nexts;
};
int n, cnt = 0;
void get_sts(string str, vector<string> &sts)
{
str += '/';
str.erase(str.begin());
string tmp;
for (size_t i = 0; i < str.size(); ++i) {
if (str[i] == '/') {
sts.push_back(tmp);
tmp = "";
} else tmp += str[i];
}
}
void build(Node* root, vector<string> sts)
{
Node* p = root;
for (size_t i = 0; i < sts.size(); ++i) {
bool flag = false;
for (size_t j = 0; j < p->nexts.size(); ++j) {
if (p->nexts[j]->name == sts[i]) {
flag = true;
p = p->nexts[j];
break;
}
}
if (flag == false) { // 新建目录
while (i != sts.size()) {
cnt++;
Node* now = new Node;
now->name = sts[i];
p->nexts.push_back(now);
++i;
p = p->nexts.back();
}
}
}
}
void calc(Node *root)
{
for (size_t i = 0; i < root->nexts.size(); ++i) {
cout << root->nexts[i]->name << endl;
calc(root->nexts[i]);
}
}
int main()
{
Node* root = new Node;
root->name = "";
cin >> n;
for (int i = 1; i <= n; ++i) {
string str;
cin >> str;
vector<string> sts;
get_sts(str, sts);
build(root, sts);
cout << cnt << endl;
}
}
二、题解中有位大佬的思路很好,让我大开眼界了(当然目前还是井底之蛙)。
他的思路乍一看就是我最早的取巧的方法,用set
自动去重文件夹的名字,统计set
元素数量即可。于是我怀着怀疑的态度去调试代码,发现他存的不是文件夹的名字,而是文件夹目录的名字!惊醒梦中人!故有此记
目录是唯一的,可以作为一个文件夹的唯一标识符。
#include <set>
#include <string>
#include <iostream>
int main() {
int n;
std::cin >> n;
std::set<std::string> set;
for (int i = 1; i <= n; ++i) {
std::string s;
std::cin >> s;
std::string dir = "";
for (size_t j = 1; j < s.size(); ++j) {
if (s[j] == '/') {
set.insert(dir);
//std::cout << dir << std::endl;
}
dir += s[j];
}
set.insert(dir);
std::cout << set.size() << std::endl;
}
}