字符串处理一直以来是我的弱项,趁着下一次考试前认真做了一下上次考试的模拟题。
我自己完全没有思路,参考了一位大牛的博客,地址在这里。这题真的很细节,做完以后我有几点反思:1.如何定义数据结构真的很关键。2.真的要非常细心,有些我自己写的bug是我对照着大牛的代码才发现的。3.要熟练掌握C++的string。
下面是代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*节点的数据结构*/
typedef struct Node
{
int father;//父节点
map<string,int> child;//孩子节点
int type;//文件类型,1代表普通文件,2代表目录文件
ll ld,lr;//目录配额,后代配额
ll ld_r,lr_r;//实际目录配额,实际后代配额
ll size;//如果是普通文件的话,文件大小
}Node;
vector<pair<int,string>> reback;//用于执行撤销操作的容器
Node node[4000010];
int num=0;//存储文件节点的数组的下标,0代表根目录节点
/*回滚函数
当执行C命令是需要创建目录,如果发生错误需要回滚*/
void Reback()
{
for(int i=0;i<reback.size();i++)
{
int id=reback[i].first;
string name=reback[i].second;
node[id].child.erase(node[id].child.find(name));
}
}
/*创建普通文件的函数*/
string CommandC()
{
string path;
ll filesize;
cin>>path>>filesize;
int last=-1;
for(int i=path.length()-1;i>=0;i--)
{
if(path[i]=='/')
{
last=i;
break;
}
}
int current=1;
int id=0;
reback.clear();
int oldnum=num;
/*处理目录文件*/
while(current<last)
{
string t="";
while(current<last&&path[current]!='/')
{
t+=path[current];
current++;
}
current++;
if(node[id].child.find(t)==node[id].child.end())//目录文件不存在,创建新文件
{
num++;
node[id].child[t]=num;
node[num].father=id;
node[num].type=2;
node[num].ld=LLONG_MAX/3;
node[num].lr=LLONG_MAX/3;
reback.push_back(make_pair(id,t));
id=num;
}
else
{
int childid=node[id].child[t];
if(node[childid].type==1)//已经存在同名普通文件
{
num=oldnum;
Reback();
return "N";
}
id=childid;
}
}
/*对普通文件的处理*/
string t="";
for(int i=last+1;i<path.length();i++)
{
t+=path[i];
}
if(node[id].child.find(t)!=node[id].child.end())//文件已存在
{
int childid=node[id].child[t];
if(node[childid].type==2)
{
num=oldnum;
Reback();
return "N";
}
}
/*判断新的改变是否满足配额要求*/
ll changesize=0;
if(node[id].child.find(t)==node[id].child.end()) changesize=filesize;//如果文件不存在,则新增大小为文件大小
else
{
int fileid=node[id].child[t];
changesize=-node[fileid].size+filesize;
}
/*检查是否满足目录配额*/
if(node[id].ld_r+changesize>node[id].ld)
{
num=oldnum;
Reback();
return "N";
}
int now=id;
/*检查对于所有的父目录,是否满足后代配额*/
while(now!=-1)
{
if(node[now].lr_r+changesize>node[now].lr)
{
num=oldnum;
Reback();
return "N";
}
now=node[now].father;
}
if(node[id].child.find(t)==node[id].child.end())//如果文件不存在,则需要创建
{
num++;
node[num].type=1;
node[num].father=id;
node[num].size=filesize;
node[id].child[t]=num;
}
else
{
node[node[id].child[t]].size=filesize;
}
node[id].ld_r=node[id].ld_r+changesize;
now=id;
while(now!=-1)
{
node[now].lr_r=node[now].lr_r+changesize;
now=node[now].father;
}
return "Y";
}
/*执行更改配额的函数*/
string CommandQ()
{
string filepath;
ll LD,LR;
cin>>filepath>>LD>>LR;
int last=-1;
int id=0;
for(int i=filepath.length()-1;i>=0;i--)
{
if(filepath[i]=='/')
{
last=i;
break;
}
}
int current=1;
if(LD==0) LD=LLONG_MAX/3;
if(LR==0) LR=LLONG_MAX/3;
/*处理路径上的目录文件*/
while(current<last)
{
string t="";
while(current<last&&filepath[current]!='/')
{
t+=filepath[current];
current++;
}
current++;
if(node[id].child.find(t)==node[id].child.end())//目录不存在
{
return "N";
}
else
{
id=node[id].child[t];
if(node[id].type==1) return "N";
}
}
/*处理目标目录*/
string t="";
for(int i=last+1;i<filepath.length();i++)
{
t+=filepath[i];
}
if(t=="") id=0;//根目录
else
{
if(node[id].child.find(t)==node[id].child.end()) return "N";
else
{
id=node[id].child[t];
}
}
if(node[id].type==1) return "N";
if(node[id].ld_r>LD||node[id].lr_r>LR) return "N";
else
{
node[id].ld=LD;
node[id].lr=LR;
return "Y";
}
}
/*处理删除文件的命令*/
string CommandR()
{
string filepath;
cin>>filepath;
int last=-1;
int current=1;
int id=0;
for(int i=filepath.length()-1;i>=0;i--)
{
if(filepath[i]=='/')
{
last=i;
break;
}
}
while(current<last)
{
string t="";
while(current<last&&filepath[current]!='/')
{
t+=filepath[current];
current++;
}
current++;
if(node[id].child.find(t)==node[id].child.end()) return "Y";
else
{
id=node[id].child[t];
}
if(node[id].type==1) return "Y";
}
string t="";
for(int i=last+1;i<filepath.length();i++)
t+=filepath[i];
if(node[id].child.find(t)==node[id].child.end()) return "Y";
int delnode=node[id].child[t];
ll delsize;
if(node[delnode].type==1)
{
delsize=node[delnode].size;
node[id].ld_r-=delsize;
node[id].child.erase(node[id].child.find(t));
}
else if(node[delnode].type==2)
{
delsize=node[delnode].lr_r;
node[id].child.erase(node[id].child.find(t));
}
int now=id;
while(now!=-1)
{
node[now].lr_r-=delsize;
now=node[now].father;
}
return "Y";
}
int main()
{
node[0].father=-1;
node[0].type=2;
node[0].ld=LLONG_MAX/3;
node[0].lr=LLONG_MAX/3;
int N;
cin>>N;
char a;
for(int i=0;i<N;i++)
{
cin>>a;
switch(a)
{
case 'C':cout<<CommandC()<<endl;break;
case 'Q':cout<<CommandQ()<<endl;break;
case 'R':cout<<CommandR()<<endl;break;
}
}
return 0;
}