588. Design In-Memory File System
Input:
["FileSystem","ls","mkdir","addContentToFile","ls","readContentFromFile"]
[[],["/"],["/a/b/c"],["/a/b/c/d","hello"],["/"],["/a/b/c/d"]]
Output:
[null,[],null,null,["a"],"hello"]
Explanation:
Last updated
Input:
["FileSystem","ls","mkdir","addContentToFile","ls","readContentFromFile"]
[[],["/"],["/a/b/c"],["/a/b/c/d","hello"],["/"],["/a/b/c/d"]]
Output:
[null,[],null,null,["a"],"hello"]
Explanation:
Last updated
// Trie
class FileSystem {
public:
class TrieNode {
public:
TrieNode() : isFile(false) {}
~TrieNode() {
for (auto& e : children) {
if (e.second) delete e.second;
}
}
unordered_map<string, TrieNode*> children;
bool isFile;
string content;
};
FileSystem() {
root = new TrieNode();
}
~FileSystem() {
delete root;
}
vector<string> ls(string path) {
vector<string> strs = split(path);
TrieNode* cur = root;
for (const string& str : strs)
cur = cur->children[str];
if (cur->isFile)
return vector<string>({strs.back()});
vector<string> res;
for (auto& e : cur->children)
res.emplace_back(e.first);
sort(res.begin(), res.end());
return res;
}
void mkdir(string path) {
vector<string> strs = split(path);
TrieNode* cur = root;
for (const string& str : strs) {
if (!cur->children.count(str))
cur->children[str] = new TrieNode();
cur = cur->children[str];
}
}
void addContentToFile(string filePath, string content) {
vector<string> strs = split(filePath);
TrieNode* cur = root;
for (const string& str : strs) {
if (!cur->children.count(str))
cur->children[str] = new TrieNode();
cur = cur->children[str];
}
cur->isFile = true;
cur->content.append(content);
}
string readContentFromFile(string filePath) {
vector<string> strs = split(filePath);
TrieNode* cur = root;
for (const string& str : strs) {
cur = cur->children[str];
}
return cur->content;
}
private:
TrieNode* root;
vector<string> split(const string& path) {
istringstream is(path);
vector<string> res;
string tmp;
while (getline(is, tmp, '/')) {
if (tmp.empty()) continue;
res.emplace_back(tmp);
}
return res;
}
};class FileSystem {
public:
FileSystem() {
}
vector<string> ls(string path) {
if (files.count(path)) {
int pos = path.find_last_of('/');
return vector<string>({path.substr(pos + 1)});
} else {
const set<string>& t = dirs[path];
return vector<string>(t.begin(), t.end());
}
}
void mkdir(string path) {
istringstream is(path);
string dir, t;
while (getline(is, t, '/')) {
if (t.empty()) continue;
if (dir.empty()) dir += "/";
dirs[dir].insert(t);
if (dir.length() > 1) dir += "/";
dir += t;
}
}
void addContentToFile(string filePath, string content) {
int pos = filePath.find_last_of('/');
string dir = filePath.substr(0, pos), file = filePath.substr(pos + 1);
if (dir.empty()) dir += "/";
if (!dirs.count(dir)) mkdir(dir);
dirs[dir].insert(file);
files[filePath].append(content);
}
string readContentFromFile(string filePath) {
return files[filePath];
}
private:
unordered_map<string, set<string> > dirs; // dir -> files and directories
unordered_map<string, string> files; // filepath -> content
};