时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 128MB,其他语言 256MB
难度:中等
描述
请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)。
文件缓存系统有两种操作:存储文件(put)和读取文件(get) 操作命令为put fileName fileSize或者get fileName
存储文件是把文件放入文件缓存系统中;读取文件是从文件缓存系统中访问已存在的文件,如果文件不存在,则不作任何操作。
当缓存空间不足以存放新的文件时,根据规则删除文件,直到剩余空间满足新的文件大小为止,再存放新文件。
具体的删除规则为:文件访问过后,会更新文件的最近访问时间和总的访问次数,当缓存不够时,按照第一优先顺序为访问次数从少到多,第二顺序为时间从老到新的方式来删除文件。
输入描述
第一行为缓存最大值m(整数,取值范围为0 < m <= 52428800)
第二行为文件操作序列个数n(0 <= n <= 300000)
从第三行起为文件操作序列,每个序列单独一行
文件操作定义为"op fileName fileSize" fileName是文件名,fileSize是文件大小
输出描述
输出当前文件缓存中的文件名列表,文件名用英文逗号分隔,按字典顺序排序
如:a,c
如果文件缓存中没有文件,则输出NONE
用例输入 1 **
50
6
put a 10
put b 20
get a
get a
get b
put c 30
用例输出 1 **
a,c
提示
-
如果新文件的文件名和文件缓存中已有的文件名相同,则不会放在缓存中
-
新的文件第一次存入到文件缓存中时,文件的总访问次数不会变化,文件的最近访问时间会更新到最新时间
-
每次文件访问后,总访问次数加1,最近访问时间更新到最新时间
-
任何两个文件的最近访问时间不会重复
-
文件名不会为空,均为小写字母,最大长度为10
-
缓存空间不足时,不能存放新文件
-
每个文件大小都是大于0的整数
#include <iostream>
#include <unordered_map>
#include <set>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct FileInfo {
string name;
int size;
int accessCount;
long long lastAccessTime;
FileInfo() : size(0), accessCount(0), lastAccessTime(0) {} // Added default constructor
FileInfo(string n, int s, long long t) :
name(n), size(s), accessCount(0), lastAccessTime(t) {}
};
class FileCache {
private:
long long maxSize; // Maximum cache size in bytes
long long currentSize; // Current occupied size
long long timeStamp; // For tracking access time
unordered_map<string, FileInfo> cache; // Main cache storage
// For sorting files by access count and time
struct Compare {
bool operator()(const FileInfo& a, const FileInfo& b) const {
if (a.accessCount != b.accessCount)
return a.accessCount < b.accessCount;
return a.lastAccessTime < b.lastAccessTime;
}
};
public:
FileCache(long long m) : maxSize(m), currentSize(0), timeStamp(0) {}
void put(string fileName, int fileSize) {
// If file already exists, do nothing
if (cache.find(fileName) != cache.end()) {
return;
}
// While there's not enough space, remove files
while (currentSize + fileSize > maxSize) {
// Find file to remove
set<FileInfo, Compare> sortedFiles;
for (auto& pair : cache) {
sortedFiles.insert(pair.second);
}
if (sortedFiles.empty()) break;
// Remove file with lowest access count and oldest time
auto toRemove = sortedFiles.begin();
currentSize -= toRemove->size;
cache.erase(toRemove->name);
}
// If there's enough space, add new file
if (currentSize + fileSize <= maxSize) {
cache[fileName] = FileInfo(fileName, fileSize, timeStamp++);
currentSize += fileSize;
}
}
void get(string fileName) {
auto it = cache.find(fileName);
if (it != cache.end()) {
it->second.accessCount++;
it->second.lastAccessTime = timeStamp++;
}
}
void printCache() {
if (cache.empty()) {
cout << "NONE" << endl;
return;
}
vector<string> files;
for (auto& pair : cache) {
files.push_back(pair.first);
}
sort(files.begin(), files.end()); // Sort alphabetically
for (int i = 0; i < files.size(); i++) {
cout << files[i];
if (i < files.size() - 1) cout << ",";
}
cout << endl;
}
};
int main() {
long long m;
int n;
cin >> m >> n;
FileCache cache(m);
for (int i = 0; i < n; i++) {
string op, fileName;
int fileSize = 0;
cin >> op >> fileName;
if (op == "put") {
cin >> fileSize;
cache.put(fileName, fileSize);
} else if (op == "get") {
cache.get(fileName);
}
}
cache.printCache();
return 0;
}