URL映射
- 規則的相鄰兩項之間用‘/’分開,所以我們先把所有項分開,然后依次把兩個字符串的對應項匹配即可。
- 分離字符串這里用字符串流(stringstream)處理,先把所有的‘/’變為空格,然后一個一個把各項分開。
- 在把‘/’變為空格的時候,要注意行末的‘/’,比如:
/okokokok 與 /okokokok/是無法匹配成功的。同樣的:/<str>/ 與/okokok也無法匹配成功。 - 模擬,注意細節和邊界即可。
1 #include<iostream> 2 #include<sstream> 3 #include<cstring> 4 #include<string> 5 #include<cstdio> 6 #include<vector> 7 #include<algorithm> 8 #define LL unsigned long long 9 using namespace std; 10 const int maxn=101; 11 int cnt1[maxn],isp,sp[maxn]; //cnt1[i]--第i個字符串的項數,isp--待查詢的字符串末尾是否為‘/’,sp[i]--第i個字符串末尾是否為‘/’ 12 string str[maxn],str1[maxn],str2; //str[i]--第i個字符串的配置信息,str1[i]--第i個映射規則,str2--當前需要被查詢的字符串 13 string sp1[maxn][maxn],sp2[maxn]; //sp1[i]--保存第i個字符串的所有項,sp2--保存當前被查詢字符串的所有項。 14 string is_num(string s){ //判斷某一項是否為整數:是--去掉前導0並返回整數;不是--返回“-” 15 int ok=0; 16 string ss=""; 17 int len=s.length(); 18 for(int i=0;i<len;i++){ 19 if(s[i]<'0'||s[i]>'9')return "-"; 20 if(ok||s[i]!='0')ss+=s[i],ok=1; 21 } 22 if(ss=="")ss="0"; 23 return ss; 24 } 25 void getinfo(string s,string s1[],int &f,int &t){ //分離並保存一個字符串的所有項,標記末尾是否為‘/’ 26 f=t=0; 27 int len=s.length(); 28 if(s[len-1]=='/')f=1; 29 for(int p=0;p<len;p++){ 30 if(s[p]=='/')s[p]=' '; 31 } 32 string ss; 33 stringstream in(s); 34 while(in>>ss)s1[t++]=ss; 35 } 36 bool match(int t,int j,string &s){ //判斷被查詢字符串與第j個規則是否能匹配 37 s=""; 38 int p1=0,p2=0; 39 while(p1<t&&p2<cnt1[j]){ 40 if(sp2[p1]==sp1[j][p2]); 41 else if(sp1[j][p2]=="<int>"){ 42 string f=is_num(sp2[p1]); 43 if(f=="-"){return 0;} 44 s+=" "+f; 45 } 46 else if(sp1[j][p2]=="<str>"){s+=" "+sp2[p1];} 47 else if(sp1[j][p2]=="<path>"){ //<path>直接全部加上 48 s+=" "+sp2[p1++]; 49 while(p1<t)s+="/"+sp2[p1++]; 50 if(isp)s+='/'; 51 return 1; 52 } 53 else return 0; 54 p1++;p2++; 55 } 56 if(isp^sp[j])return 0; //末尾判斷--同時有‘/’或同時無‘/’才能匹配 57 if(p1!=t||p2!=cnt1[j])return 0; //完全匹配 58 return 1; 59 } 60 int main(){ 61 freopen("in.txt","r",stdin); 62 int n,m; 63 cin>>n>>m; 64 for(int i=0;i<n;i++){ 65 cin>>str1[i]>>str[i]; 66 getinfo(str1[i],sp1[i],sp[i],cnt1[i]); //string, split, 末尾是否'/', 字符串數量 67 } 68 for(int i=0;i<m;i++){ 69 string ans; 70 int cnt=0;isp=0; 71 cin>>str2; 72 getinfo(str2,sp2,isp,cnt); 73 bool ok=0; 74 for(int j=0;j<n;j++){ 75 if(match(cnt,j,ans)){ 76 cout<<str[j]<<ans<<endl;; 77 ok=1;break; 78 } 79 } 80 if(!ok)cout<<404<<endl; 81 } 82 return 0; 83 }
路徑解析
以及末尾有/
1 #include<iostream> 2 #include <string> 3 #include <vector> 4 using namespace std; 5 int main() 6 { 7 int num,pos,pos1; 8 string curDir,line; 9 cin >> num >> curDir; 10 getchar(); // 使用getline要注意處理回車符 11 while (num--) 12 { 13 getline(cin, line); // 讀空字符串 14 15 if (line.empty())line = curDir; // 16 else if (line[0] != '/')line = curDir + "/" + line; // 1.首位不為'/'的情況,將相對路徑轉化為絕對路徑 17 18 while ((pos = line.find("//")) != -1) line.erase(pos, 1);// 2.出現/// 19 20 while ((pos = line.find("/../")) != -1) // 3.出現/../ 21 { 22 if (!pos)line.erase(0, 3); 23 else{ 24 pos1 = line.rfind("/", pos - 1); 25 line.erase(pos1, pos - pos1 + 3); 26 } 27 } 28 while ((pos = line.find("/./")) != -1)line.erase(pos, 2);// 4.出現/./ 29 30 if (line.size()>1 && line[line.size() - 1] == '/')line.erase(line.size() - 1, 1);// 5.末尾有/ 31 32 cout << line << endl; 33 } 34 return 0; 35 }、
——如果用cin>>line的方式輸入string類型的line,會導致不能判斷為空的輸入,所以采用getline。在while循環之前還需要添加getchar(),吸收換行。否則90分;
——c++中單雙引號的區別:
""是字符串,C風格字符串后面有一個'\0';''是一個字符,一共就一字節。
單引號表示是字符變量值,字母的本質也是數字。雙引號表示字符串變量值,給字符串賦值時系統會自動給字符串變量后面加上一個\0來表示字符串結尾。
string::rfind(string, pos) 是從頭開始找,到pos為止,最后一次出現string的位置。
權限查詢
map的靈活運行,給出集合A和集合B,集合B和集合C的關系,計算集合C和集合A的關系,因為會出現重疊的元素,所以要遍歷所有的A集合中的元素,取最大。
用到知識點:
map<string, map<string, int>>
map::count() 返回0,1
map<string, int>::iterator it--it->first, it->second
string::substr(start, len)--s.substr(0,3)
string::find(string)返回找到的pos,-1
#include <iostream> #include <vector> #include <string> #include <map> using namespace std; map<string,int> cate; map<string,map<string, int> > rol; map<string,map<string,int> > usr; void find(string u, string role, int level){ if(usr.count(u)>0&&usr[u].count(role)>0) { int lev = usr[u][role]; if(level==-1) { if(lev>-1)cout<<lev<<endl; else cout<<"true"<<endl; } else { if(lev<level)cout<< "false"<<endl; else cout<<"true"<<endl; } } else cout<<"false"<<endl; } int to_int(string s,int pos) { int ans=0; for(int i=pos;i<s.size();i++) { ans = ans*10 + s[i]-'0'; } return ans; } int main() { int p,r,u,q; cin>>p; string s; int level; size_t pos; for(int i=0;i<p;i++) { cin >> s; if ((pos = s.find(":")) != -1) { level = to_int(s,pos+1); s = s.substr(0,pos); cate[s]=max(cate[s],level); } else cate[s]=-1; } cin>>r; int cnt; string role; for(int i=0;i<r;i++) { cin>>role>>cnt; for(int j=0;j<cnt;j++) { cin>>s; if ((pos = s.find(":")) != -1) { level = to_int(s,pos+1); s = s.substr(0,pos); rol[role][s]=max(rol[role][s],level); } else rol[role][s]=-1; } } cin>>u; for(int i =0;i<u;i++) // 直接和cate通過role關聯 { string name; cin>>name>>cnt; for(int j=0;j<cnt;j++) { cin>>s; map<string,int>::iterator it = rol[s].begin(); while(it!=rol[s].end()) { if(usr[name].count(it->first)>0)// 這里必須要區分是否存在,否則默認的0會覆蓋-1 { usr[name][it->first]=max(usr[name][it->first],it->second); } else usr[name][it->first] = it->second; it++; } } } cin>>q; while(q--) { string x; cin>>s>>x; size_t pos=x.find(":"); if(pos==string::npos) find(s,x,-1); else find(s,x.substr(0,pos),x[pos+1]-'0');//string_to_int的另一種寫法 } return 0; }
JSON查詢
解法轉自meelo
json是一個遞歸數據結構,因此可以使用函數的遞歸調用來進行解析。
每一類數據對應一個解析函數,代碼中parseString實現解析字符串的功能,parseObject實現解析對象的功能。
解析函數的主體功能就是依次遍歷每一個字符,根據字符判斷是否是字符串的開始、對象的開始……並進行相應的處理。
json是一個鍵值對的結構,因此可以用map存儲。map的鍵可以用查詢的格式,用小數點.來分隔多層的鍵。
1 #include <iostream> 2 #include <cassert> 3 #include <map> 4 using namespace std; 5 6 string parseString(string &str, int &i) { 7 string tmp; 8 if(str[i] == '"') i++; 9 else assert(0); 10 11 while(i < str.size()) { 12 if(str[i] == '\\') { 13 i++; 14 tmp += str[i]; 15 i++; 16 } 17 else if(str[i] == '"') { 18 break; 19 } 20 else { 21 tmp += str[i]; 22 i++; 23 } 24 } 25 26 if(str[i] == '"') i++; 27 else assert(0); 28 29 return tmp; 30 } 31 32 void parseObject(string &str, string prefix, map<string, string> &dict, int &i) { 33 if(str[i] == '{') i++; 34 else assert(0); 35 36 string key, value; 37 bool strType = false; // 標志 false:key, true:value 38 while(i < str.size()) { 39 if(str[i] == '"') { 40 string tmp = parseString(str, i); 41 if(strType) { // value 42 value = tmp; 43 dict[key] = value; 44 } 45 else { // key 46 key = prefix + (prefix==""?"":".") + tmp; 47 } 48 } 49 else if(str[i] == ':') { 50 strType = true; 51 i++; 52 } 53 else if(str[i] == ',') { 54 strType = false; 55 i++; 56 } 57 else if(str[i] == '{') { 58 dict[key] = ""; 59 parseObject(str, key, dict, i); 60 } 61 else if(str[i] == '}') { 62 i++; 63 break; 64 } 65 else { 66 i++; 67 } 68 } 69 } 70 71 int main() { 72 int N, M; 73 cin >> N >> M; 74 string json; 75 if(cin.peek()=='\n') cin.ignore(); 76 for(int n=0; n<N; n++) { // 輸入用getline(保留空格,空)連成一個string 77 string tmp; 78 getline(cin, tmp); 79 json += tmp; 80 } 81 map<string, string> dict; // 存儲所有候選鍵值對 82 int i = 0; 83 parseObject(json, "", dict, i); // json是一個遞歸結構,遞歸解析 84 string query; 85 for(int m=0; m<M; m++) { 86 getline(cin, query); 87 if(dict.find(query) == dict.end()) { 88 cout << "NOTEXIST\n"; 89 } 90 else { 91 if(dict[query] == "") { 92 cout << "OBJECT\n"; 93 } 94 else { 95 cout << "STRING " << dict[query] << "\n"; 96 } 97 } 98 } 99 return 0; 100 }
MarkDown
解法轉自:meelo 邏輯異常清晰,這老哥寫的代碼會說話2333
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <cassert> 5 6 using namespace std; 7 8 string to_string(int i) { 9 char buffer[10]; 10 return string(itoa(i, buffer, 10)); 11 } 12 13 string parseEmphasize(string text) { 14 string result; 15 result += "<em>"; 16 result += text; 17 result += "</em>"; 18 return result; 19 } 20 21 string parseLink(string text, string link) { 22 string result; 23 result += "<a href=\""; 24 result += link; 25 result += "\">"; 26 result += text; 27 result += "</a>"; 28 return result; 29 } 30 31 string parseLine(string line) { // 行內解析,包含遞歸調用 32 string result; 33 int i = 0; 34 while(i<line.size()) { 35 if(line[i]=='[') { 36 string text, link; 37 int j = i+1; 38 while(line[j] != ']') j++; 39 text = line.substr(i+1, j-i-1); 40 i = j+1; 41 assert(line[i]=='('); 42 while(line[j]!=')') j++; 43 link = line.substr(i+1, j-i-1); 44 45 text = parseLine(text); 46 link = parseLine(link); 47 result += parseLink(text, link); 48 i = j+1; 49 } 50 else if(line[i]=='_') { 51 string text; 52 int j = i+1; 53 while(line[j]!='_') j++; 54 text = line.substr(i+1, j-i-1); 55 56 text = parseLine(text); 57 result += parseEmphasize(text); 58 i = j + 1; 59 } 60 else { 61 result += line[i]; 62 i++; 63 } 64 } 65 return result; 66 } 67 68 string parseHeading(vector<string> &contents) { 69 assert(contents.size()==1); 70 int level = 1; 71 int i = 0; 72 string heading = parseLine(contents[0]); 73 74 while(heading[i] == '#') i++; 75 level = i; 76 while(heading[i] == ' ') i++; 77 78 string result; 79 result += "<h"; 80 result += to_string(level); 81 result += '>'; 82 result += heading.substr(i,-1); 83 result += "</h"; 84 result += to_string(level); 85 result += ">\n"; 86 return result; 87 } 88 89 string parseParagraph(vector<string> &contents) { 90 string result; 91 result += "<p>"; 92 for(int i=0; i<contents.size(); i++) { 93 result += parseLine(contents[i]); 94 if(contents.size() != 0 && i != contents.size()-1) result += '\n'; 95 } 96 result += "</p>\n"; 97 return result; 98 } 99 100 string parseUnorderedList(vector<string> &contents) { 101 string result; 102 result += "<ul>\n"; 103 int j; 104 for(int i=0; i<contents.size(); i++) { 105 result += "<li>"; 106 j = 1; 107 while(contents[i][j] == ' ') j++; 108 result += parseLine(contents[i].substr(j,-1)); 109 result += "</li>\n"; 110 } 111 result += "</ul>\n"; 112 return result; 113 } 114 115 int main() { 116 string line; 117 vector<string> contents; 118 int blockType; // 0:empty, 1:paragraph, 2:heading, 3:unordered list 119 string result; 120 while(getline(cin, line) || contents.size()>0) { // getline空行的時候注意 121 if(line.empty()) { // 結束的標志 122 if(blockType != 0) { 123 switch(blockType) { 124 case 1: result += parseParagraph(contents); break; 125 case 2: result += parseHeading(contents); break; 126 case 3: result += parseUnorderedList(contents); break; 127 } 128 contents.resize(0); 129 blockType = 0; 130 } 131 } 132 else if(line[0] == '#') { 133 contents.push_back(line); 134 blockType = 2; 135 } 136 else if(line[0] == '*') { 137 contents.push_back(line); 138 blockType = 3; 139 } 140 else { 141 contents.push_back(line); 142 blockType = 1; 143 } 144 line = ""; 145 } 146 cout << result; 147 }