问题描述
试题编号: | 201803-3 |
试题名称: | URL映射 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 URL 映射是诸如 Django、Ruby on Rails 等网页框架 (web frameworks) 的一个重要组件。对于从浏览器发来的 HTTP 请求,URL 映射模块会解析请求中的 URL 地址,并将其分派给相应的处理代码。现在,请你来实现一个简单的 URL 映射功能。 输入格式 输入第一行是两个正整数 n 和 m,分别表示 URL 映射的规则条数和待处理的 URL 地址个数,中间用一个空格字符分隔。 输出格式 输入共 m 行,第 i 行表示 qi 的匹配结果。如果匹配成功,设匹配了规则 pj ,则输出对应的 rj。同时,如果规则中有参数,则在同一行内依次输出匹配后的参数。注意整数参数输出时要把前导零去掉。相邻两项之间用一个空格字符分隔。如果匹配失败,则输出 404。 样例输入 5 4 样例输出 year_archive 2004 样例说明 对于第 1 个地址 /articles/2004/,无法匹配第 1 条规则,可以匹配第 2 条规则,参数为 2004。 数据规模和约定 1 ≤ n ≤ 100,1 ≤ m ≤ 100。 |
一开始的思路是先对规则做处理,根据"/"做划分,用一个结构体rule来记录结果
class rule
{
public:
string name; // 规则名称
vector<string> content; // 划分后的每个内容 例如/<int>/abc 那么content为<int> abc /(末尾如果为/也要记录进content)
rule(string a, vector<string> b) :name(a), content(b) {}
};
用一个handle函数来进行处理
void handle(string s, string name)
{
int i, j, k;
int spi;
string str;
vector<string> content;
bool isslash = true;
if (s[s.length() - 1] != '/'){
isslash = false;
s = s + "/";
}
spi = s.find("/");
while (spi != -1) {
str = s.substr(0, spi);
s = s.substr(spi + 1, s.length());
content.push_back(str);
spi = s.find("/");
}
if (isslash)
content.push_back("/"); // 末尾如果为"/"也记录进content
rules.push_back(rule(name, content));
}
接着就是开始匹配,即每个规则的content与每个带匹配的ur进行逐个匹配,用一个循环
匹配过程中若是遇到参数<int><str>等,则记录到一个vector中,这里命名为result
循环如下
for (i = 0; i < rules[k].content.size() && urIndex < ur.size(); i++) {
if (rules[k].content[i] == "<path>" && ur[urIndex].length() != 0) { // <path>后全为参数 可直接结束
str = ur[urIndex];
for (j = urIndex + 1; j < ur.size(); j++) { // 直接添加之后的所有路径作为参数
if (ur[j] == "/") // 若末尾是'/' 直接添加
str = str + "/";
else
str = str + "/" + ur[j];
}
result.push_back(str);
urIndex = ur.size(); // <path>后直接全部作为参数 urIndex指向末尾表示匹配完成
i = rules[k].content.size(); // <path>后直接全部作为参数 i指向末尾表示匹配完成
}
else if (rules[k].content[i] == "<int>" && ur[urIndex].length() != 0) { // <int>
if (judgeNum(ur[urIndex])) { // 如果待匹配路径为数字(与<int>匹配)
result.push_back(int_to_string(string_to_int(ur[urIndex]))); // 添加参数
urIndex++;
}
else {
ifMatch = false;
break;
}
}
else if (rules[k].content[i] == "<str>" && ur[urIndex].length() != 0) { // <str>
result.push_back(ur[urIndex]); // <str>直接匹配 添加参数
urIndex++;
}
else {
if (rules[k].content[i] == ur[urIndex]) {
urIndex++; // 匹配路径
}
else { // 路径不匹配
ifMatch = false;
break;
}
}
}
if (urIndex != ur.size() || i<rules[k].content.size()) // 双方未匹配完 匹配失败
ifMatch = false;
总体思路就是这样,这里要强调的是一些坑
例如规则若是为 /abc/<int> test
输入的为 /abc/1 则可以匹配,若是输入为 /abc/1/ 则匹配失败
这是题目没有讲清楚的,为了处理这种情况,所以末尾的"/"我也当成要匹配的一部分
若是 规则为/abc/<path>
输入为 /abc/123/ 还是/abc/123 均正确 不过输出的参数分别为 123/ 与 123
代码如下
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<vector>
#include<string>
#include<string.h>
#include<sstream>
using namespace std;
class rule
{
public:
string name;
vector<string> content;
rule(string a, vector<string> b) :name(a), content(b) {}
};
vector<rule> rules;
bool ifMatch;
int string_to_int(string s)
{
int ans;
stringstream ss(s);
ss >> ans;
return ans;
}
string int_to_string(int a)
{
stringstream ss;
ss << a;
return ss.str();
}
bool judgeNum(string s)
{
for (int i = 0; i<s.length(); i++)
if (s[i]>'9' || s[i]<'0') return false;
return true;
}
void handle(string s, string name)
{
int i, j, k;
int spi;
string str;
vector<string> content;
bool isslash = true;
if (s[s.length() - 1] != '/') {
isslash = false;
s = s + "/";
}
spi = s.find("/");
while (spi != -1) {
str = s.substr(0, spi);
s = s.substr(spi + 1, s.length());
content.push_back(str);
spi = s.find("/");
}
if (isslash)
content.push_back("/");
rules.push_back(rule(name, content));
}
vector<string> match(int k, string url)
{
int i, j;
int spi;
string str;
bool isslash = true;
vector<string> result;
vector<string> ur;
if (url[url.length() - 1] != '/') {
isslash = false;
url = url + "/";
}
int urIndex = 0;
spi = url.find("/");
while (spi != -1) {
str = url.substr(0, spi);
url = url.substr(spi + 1, url.length());
ur.push_back(str);
spi = url.find("/");
}
if (isslash)
ur.push_back("/");
for (i = 0; i < rules[k].content.size() && urIndex < ur.size(); i++) {
if (rules[k].content[i] == "<path>" && ur[urIndex].length() != 0) { // <path> 后面一定是结束了
str = ur[urIndex];
for (j = urIndex + 1; j < ur.size(); j++) { // 直接添加之后的所有路径作为参数
if (ur[j] == "/") // 若末尾是'/' 直接添加
str = str + "/";
else
str = str + "/" + ur[j];
}
result.push_back(str);
urIndex = ur.size(); // <path>后直接全部作为参数 urIndex指向末尾表示匹配完成
i = rules[k].content.size(); // <path>后直接全部作为参数 i指向末尾表示匹配完成
}
else if (rules[k].content[i] == "<int>" && ur[urIndex].length() != 0) { // <int>
if (judgeNum(ur[urIndex])) { // 如果待匹配路径为数字(与<int>匹配)
result.push_back(int_to_string(string_to_int(ur[urIndex]))); // 字符串转数字后再转字符串 去除0
urIndex++;
}
else {
ifMatch = false;
break;
}
}
else if (rules[k].content[i] == "<str>" && ur[urIndex].length() != 0) { // <str>
result.push_back(ur[urIndex]); // <str>直接匹配
urIndex++;
}
else {
if (rules[k].content[i] == ur[urIndex]) {
urIndex++;
}
else {
ifMatch = false;
break;
}
}
}
// 未匹配完
if (urIndex != ur.size() || i < rules[k].content.size())
{
ifMatch = false;
}
return result;
}
int main()
{
int n, m, i, j, k;
string format, name, url;
cin >> n >> m;
for (i = 0; i<n; i++) {
cin >> format >> name;
format = format.substr(1, format.length());
handle(format, name);
}
for (i = 0; i<m; i++) {
cin >> url;
url = url.substr(1, url.length());
// 开始逐个匹配
for (j = 0; j<n; j++) {
ifMatch = true;
vector<string> vec = match(j, url);
if (ifMatch) {
cout << rules[j].name;
for (int h = 0; h<vec.size(); h++)
cout << " " << vec[h];
cout << endl;
break;
}
}
if (j == n) cout << "404" << endl;
}
return 0;
}