NC14116. Simple Database
描述
输入描述
第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是一个整数n(0 ≤ n ≤ 1000),表示操作语句的数量,
接下来n行,每行是一个字符串,表示操作语句。
请注意操作语句中空格位置及数量,保证操作语句严格符合语法。
输出描述
对于第k组测试数据,先输出一行"Case #k:"(不含引号),
对于每个查询语句,按照给定的输出格式输出查询结果,
对于每个不合法操作,输出一行"error"(不含引号)。
保证输出文件大小不超过10MB。
示例1
输入:
1 10 CREATE person (name) DROP person CREATE person (name, age, gender) INSERT person ("quailty", "20", "male") SELECT person WHERE age = "20" UPDATE person SET name = "fzirsqh" WHERE age = "20", gender = "male" SELECT person WHERE name = "quailty" DELETE person SELECT person WHERE rating = "2323" DROP person
输出:
Case #1: name age gender quailty 20 male name age gender error
说明:
敢写敢过。C++11(clang++ 3.9) 解法, 执行用时: 244ms, 内存消耗: 10160K, 提交时间: 2019-01-07 12:09:21
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<list> #include<queue> #include<map> using namespace std; bool IsValidChar(char x) { if(x>='A' && x<='Z')return 1; if(x>='a' && x<='z')return 1; if(x>='0' && x<='9')return 1; return x=='_'; } const string command[7]= { "","CREATE","DROP","INSERT","DELETE","UPDATE","SELECT" }; map<string,int>keyOfTable; struct Table { static int capacity; string name; map<string,int>keyOfList; vector<list<string> >value; }; int Table::capacity=0; vector<Table>database; queue<int>recycle; struct Analyser { int type; string table_name; vector<string>list_name; vector<pair<string,string> >target; vector<pair<string,string> >limit; Analyser(){} Analyser(string sentence) { stringstream stream(sentence); string word; stream>>word; for(int i=1;i<=6;i++) if(word==command[i])type=i; stream>>table_name; switch(type) { case 1: case 3: { while(stream>>word) { int l=0,r=(int)word.size()-1; while(!IsValidChar(word[l]))l++; while(!IsValidChar(word[r]))r--; list_name.push_back(word.substr(l,r-l+1)); } break; } case 4: case 5: case 6: { bool isLimit=0,isValue=0; string key,value; while(stream>>word) { if(word=="WHERE") { isLimit=1; continue; } if(word=="SET" || word=="=")continue; int l=0,r=(int)word.size()-1; while(!IsValidChar(word[l]))l++; while(!IsValidChar(word[r]))r--; if(!isValue) { key=word.substr(l,r-l+1); isValue=1; } else { value=word.substr(l,r-l+1); if(!isLimit)target.push_back(make_pair(key,value)); else limit.push_back(make_pair(key,value)); isValue=0; } } } break; default: break; } } }; void Create(Analyser &working) { int id=0; if(recycle.empty())id=Table::capacity++,database.push_back(Table()); else id=recycle.front(),recycle.pop(); keyOfTable[working.table_name]=id; database[id]=Table(); database[id].name=working.table_name; for(int i=0;i<(int)working.list_name.size();i++) database[id].keyOfList[working.list_name[i]]=i; database[id].value.resize((int)working.list_name.size()); for(int i=0;i<(int)working.list_name.size();i++) database[id].value[i].push_back(working.list_name[i]); } void Drop(Analyser &working) { int id=keyOfTable[working.table_name]; recycle.push(id); keyOfTable.erase(working.table_name); } void Insert(Analyser &working) { int id=keyOfTable[working.table_name]; for(int i=0;i<(int)working.list_name.size();i++) database[id].value[i].push_back(working.list_name[i]); } void Others(Analyser &working) { int id=keyOfTable[working.table_name]; for(int i=0;i<(int)working.target.size();i++) if(database[id].keyOfList.find(working.target[i].first)==database[id].keyOfList.end()) { cout<<"error"<<endl; return; } for(int i=0;i<(int)working.limit.size();i++) if(database[id].keyOfList.find(working.limit[i].first)==database[id].keyOfList.end()) { cout<<"error"<<endl; return; } list<string>::iterator *itr=new list<string>::iterator[(int)database[id].value.size()]; for(int i=0;i<(int)database[id].value.size();i++) { itr[i]=database[id].value[i].begin(); if(working.type==6) { if(i>0)cout<<" "; cout<<*itr[i]; if(i==(int)database[id].value.size()-1)cout<<endl; } itr[i]++; } while(itr[0]!=database[id].value[0].end()) { bool isMatch=1; for(int i=0;i<(int)working.limit.size();i++) if(*itr[database[id].keyOfList[working.limit[i].first]]!=working.limit[i].second) isMatch=0; if(isMatch && working.type==5) for(int i=0;i<(int)working.target.size();i++) *itr[database[id].keyOfList[working.target[i].first]]=working.target[i].second; for(int i=0;i<(int)database[id].value.size();i++) { if(isMatch) { switch(working.type) { case 4: database[id].value[i].erase(itr[i]++); break; case 6: if(i>0)cout<<" "; cout<<*itr[i]++; if(i==(int)database[id].value.size()-1)cout<<endl; break; default: itr[i]++; break; } } else itr[i]++; } } delete[] itr; } void Init() { Table::capacity=0; keyOfTable.clear(); database.clear(); while(!recycle.empty())recycle.pop(); } void Process() { Init(); int n; cin>>n; string sentence; getline(cin,sentence); while(n--) { getline(cin,sentence); Analyser working(sentence); if((working.type==1 && keyOfTable.find(working.table_name)!=keyOfTable.end()) ||(working.type>1 && keyOfTable.find(working.table_name)==keyOfTable.end())) { cout<<"error"<<endl; continue; } switch(working.type) { case 1: Create(working); break; case 2: Drop(working); break; case 3: Insert(working); break; case 4: case 5: case 6: Others(working); break; default: break; } } } int main() { ios::sync_with_stdio(false); int T; cin>>T; for(int i=1;i<=T;i++) { cout<<"Case #"<<i<<":"<<endl; Process(); } return 0; }