CCF 元素选择器
这题我写了半天最终也只能得40分,由于代码过于丑陋此处就不予展示。
下面这份代码由一位巨佬给出。优美的程序真是让人拍案叫绝·······
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 105;
struct Selector {
int row;
int rank;
string label;
string id;
};
int n, m;
Selector sel[MAXN];
string html, css;
int main() {
scanf("%d%d", &n, &m);
getchar();
for (int i = 1; i <= n; i++) {
getline(cin, html);
sel[i].row = i;
istringstream ss(html);
string str;
ss >> str;
int cd;
for (cd = 0; str[cd] == '.'; cd++);
sel[i].rank = cd / 2; //计算层级
sel[i].label = str.substr(cd); //获取标签
transform(sel[i].label.begin(), sel[i].label.end(), sel[i].label.begin(), ::tolower); //转换小写
while (ss >> str) { //获取id属性
if (str[0] == '#') sel[i].id = str;
}
}
for (int i = 0; i < m; i++) {
getline(cin, css);
istringstream ss(css);
vector<string> query;
string str;
while (ss >> str) { //存储查询条件
if (str[0] != '#') {
transform(str.begin(), str.end(), str.begin(), ::tolower);
}
query.push_back(str);
}
//查询条件的最后一个标签或属性是关键字
int ans[MAXN]; //存储满足条件的行数
int cnt = 0; //计数
int num; //实际满足条件的个数
vector<string>::reverse_iterator it = query.rbegin();
for (int j = 1; j <= n; j++) {
if (sel[j].id == *it || sel[j].label == *it) {
ans[cnt++] = j;
}
}
num = cnt;
for (int c = 0; c < cnt; c++) { //遍历每个关键字,判断是否满足条件
it = query.rbegin() + 1;
int mrank = sel[ans[c]].rank;
for (int j = ans[c] - 1; it != query.rend() && j > 0; j--) {
if (sel[j].rank < mrank && (*it == sel[j].label || *it == sel[j].id)) {
it++;
mrank = sel[j].rank;
}
}
if (it != query.rend()) {
ans[c] = 0;
num--;
}
}
cout << num;
for (int j = 0; j < cnt; j++) {
if (ans[j]) {
cout << " " << ans[j];
}
}
cout << endl;
}
return 0;
}
CCF url映射
- 这道题我的思路又是错的。(也不能说是错误的思路,只是按照我的思路写下去程序会非常麻烦)既然要输出最后匹配的字符串,如果是先匹配再输出的话,必然要弄一个数组记录匹配的是哪一个,没匹配的是哪一个,这样还不如一遍匹配一边输出。我们可以用一个布尔值来控制函数是只匹配不输出还是既要匹配还要输出。
- 这里完全没有必要一个词一个词的去匹配url映射,显然这种做法会增加编程的负担。我必须想办法将url中的单词和数字提取出来,而这样做实际上是没有必要的。既然匹配的时候是大小写敏感的,那完全可以一个字母一个字母的去匹配
错误思路代码(50分)
又臭又长,还不讨好······
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
#define MAX 110
#define INT 2
#define PATH 3
#define STR 4
#define COM 5
struct ele {
string E;
int type;
};
struct Url {
vector<ele>Ele;
string name;
}Urls[MAX];
void Deal(const string& t, vector<ele>&Element)
{
int left = 0;
int right;
//vector<ele>& Element = Urls[loc].Ele;
for (right = 1; right < t.size(); right++)
{
if (t[right] == '/' && t[right - 1] == '>')
{
if (t[left + 2] == 's')
{
Element.push_back({ "",STR });
}
else if (t[left + 2] == 'i')
{
Element.push_back({ "",INT });
}
else if (t[left + 2] == 'p')
{
Element.push_back({ "",PATH });
}
left = right;
continue;
}
else if(t[right]=='/')
{
Element.push_back({ t.substr(left + 1,right - left - 1),COM });
left = right;
continue;
}
}
if (t[t.size() - 1] == '>' && t[t.size() - 2] == 'h')
{
Element.push_back({ "",PATH });
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
freopen("sb.txt", "r", stdin);
int m, n;
cin >> m >> n;
cin.get();
for (int i = 0; i < m; i++)
{
string t;
getline(cin, t);
if (t.find('?') != string::npos)
continue;
int base = t.find(' ');
Urls[i].name = t.substr(base + 1);
Deal(t.substr(0, base), Urls[i].Ele);
}
for (int i = 0; i < m; i++)
{
cout << Urls[i].name << " ";
for (auto& c : Urls[i].Ele)
{
cout << c.E << " "<<c.type<<" ";
}
cout << endl;
}
for (int i = 0; i < n; i++)
{
string t;
getline(cin, t);
int left = 0;
int right = 0;
vector<ele>Element;
Deal(t, Element);
bool find = false;
/*for (auto c : Element)
{
cout << c.E << " " << c.type << " ";
}
cout << endl;
*/
for (int k = 0; k < m; k++)
{
bool path = false;
for (int l = 0; l < Urls[k].Ele.size(); l++)
{
if (Urls[k].Ele[l].type == PATH)
path = true;
}
if (!path && Urls[k].Ele.size() != Element.size())continue;//没有path而且数量不相同
else if (!path && Urls[k].Ele.size() == Element.size())
{
bool yes = true;
for (int u= 0; u < Element.size(); u++)
{
bool a = !(Element[u].E == Urls[k].Ele[u].E);
bool b = !(isdigit(Element[u].E[0]) && (Urls[k].Ele[u].type == INT));
bool c = !(isalpha(Element[u].E[0]) && (Urls[k].Ele[u].type == STR));
if (a && b && c)
yes = false;
}
if (yes)
{
find = true;
cout << Urls[k].name ;
for (int u = 0; u < Element.size(); u++)
{
if (Urls[k].Ele[u].type == STR)
cout<<" " << Element[u].E;
else if (Urls[k].Ele[u].type == INT)
{
int p = 0;
while (Element[u].E[p]=='0')
{
p++;
}
cout<<" " << Element[u].E.substr(p);
}
}
cout << endl;
}
}
else if (path)
{//假设path都只是出现在最后一个位置
if (Urls[k].Ele.size() <= Element.size())
{
bool yes = true;
for (int u = 0; u < Urls[k].Ele.size() - 1; u++)
{
bool a = !(Element[u].E == Urls[k].Ele[u].E);
if (a)
yes = false;
}
if (yes)
{
find = true;
int base = t.find(Element[Urls[k].Ele.size() - 1].E);
cout << Urls[k].name << " ";
cout << t.substr(base) << endl;
}
}
}
}
if (!find)
cout << 404 << endl;
}
return 0;
}
大佬代码
思路简单,结构清晰,目的明确,令人震惊。
/* CCF201803-3 URL映射 */
#include <iostream>
#include <ctype.h>
using namespace std;
const int N = 100;
string p[N], r[N], s;
bool match(string& s, string& t, bool flag)
{
int lent = t.size();
int lens = s.size();
int ps = 0, pt = 0;
while (ps < lens && pt < lent) {
if (t[pt] == s[ps]) {
ps++, pt++;
}
else {
// 匹配<xxx>
if (t[pt++] != '<')
return false;
if (flag)
cout << ' ';
if (t[pt] == 'i') {
// 匹配<int>
bool ok = false;
while (s[ps] && isdigit(s[ps])) {
if (s[ps] != '0')
ok = true;
if (flag && ok)
cout << s[ps];
ps++;
}
if (!ok)
return false;
pt += 4;
}
else if (t[pt] == 's') {
// 匹配<str>
bool ok = false;
while (s[ps] && s[ps] != '/') {
ok = true;
if (flag)
cout << s[ps];
ps++;
}
if (!ok)
return false;
pt += 4;
}
else if (t[pt] == 'p') {
// 匹配<path>
if (flag)
while (s[ps])
cout << s[ps++];
return true;
}
}
}
return pt == lent && ps == lens;
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> p[i] >> r[i];
for (int i = 0; i < m; i++) {
cin >> s;
bool flag = true;
for (int j = 0; flag && j < n; j++)
if (match(s, p[j], false)) {
flag = false;
cout << r[j];
match(s, p[j], true);
}
if (flag)
cout << "404";
cout << endl;
}
return 0;
}