CCF-CSP 第三題字符串整理(模擬大法好)


URL映射

  1. 規則的相鄰兩項之間用‘/’分開,所以我們先把所有項分開,然后依次把兩個字符串的對應項匹配即可。
  2. 分離字符串這里用字符串流(stringstream)處理,先把所有的‘/’變為空格,然后一個一個把各項分開。
  3. 在把‘/’變為空格的時候,要注意行末的‘/’,比如:
    /okokokok  與  /okokokok/是無法匹配成功的。同樣的:/<str>/ 與/okokok也無法匹配成功。
  4. 模擬,注意細節和邊界即可。
 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

Markdown分為區塊結構和行內結構。
區塊結構的類型可以根據第一個符號進行辨別,區塊結構結束的可以通過空行來辨別。
行內結構與區塊結構的處理不同,則需要分析每一行的內容。
因此程序的兩個主題部分: 分割區塊、處理行內結構。處理區塊結構的邏輯在main函數中,處理行內結構的邏輯在parseLine函數中。
每一種語法對應於一個函數。
  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM