201803-3 CSP认证 URL映射100分(中等难度-字符串模拟)

题目大意:

       定义n个URL匹配规则,以及m个URL地址,询问每一个URL地址,第一个和该地址匹配的URL规则。 

       <int>  和   数字    匹配,但是不能带 ‘ / ’这个划线分割的东西。

       <str> 和    字符串匹配,但是不能带 ‘ / ’这个划线分割的东西。

       <path>和   路径匹配 , 中间可以带这个 ‘ / ’ 。

需要注意哪些点:

       1.           

               在题目中有这样一句话。保证输入都合法,但是地址并不保证,所以要手动判断地址是否合法。

       2.     如果是<int>匹配的话一定要把匹配到的前导零去掉

       3.     注意文中提到过,URL规则结束 和  斜线 两个定义 , URL结束就是没有斜线,所以如果规则最后的不是<path>,

                那么就算前边匹配上了,但是最后一个字符不都是斜线,也是匹配不上的。

                也就是说   “ /articles/2004 “ 这个和样例中的第一条规则是匹配不上的,就因为最后的斜线。

模拟步骤:

      1.     将字符串按照斜线分割,每一部分都存起来到C数组,并用sz数组记录有几个部分。

      2.     将询问字符串的正确性,并将每部分存入kk数组中,等待匹配。

      3.     遍历规则逐一匹配,同时注意上边的3个细节。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
int n,m;
int sz[105];
string C[105][105];
string s[105],lyt[105];
string kk[105],ans[105];
int idx_p = -1,tot_p = 0,tot_k;
bool judge_int(string s) ///判断是不是可以和<int>匹配
{
    int len = s.size();
    for(int i=0;i<len;i++){
        if(s[i]>='0' && s[i]<='9')continue;
        else return 0;
    }
}
bool check(int x)  ///判断当前kk里的内容可不可以和x号规则匹配
{
    int len = sz[x];
    for(int i=1;i<=len;i++){
        if(i > tot_k)return 0;
        if(C[x][i] == "<int>"){  ///匹配int
            if(judge_int(kk[i])){
                string tt = "";
                int lenk = kk[i].size(),idx= 0; ///去前导零
                for(int j = 0;j<lenk;j++){
                    if(kk[i][j] != '0'){idx = j;break;}
                }
                for(int j = idx;j<lenk;j++){
                    tt += kk[i][j];
                }
                ans[++tot_p] = tt;
                continue;
            }
            else return 0;
        }
        if(C[x][i] == "<str>"){   ///匹配str
            ans[++tot_p] = kk[i];
            continue;
        }
        if(C[x][i] == "<path>"){  ///如果是path后边都匹配
            idx_p = i;
            return 1;
        }
        if(C[x][i] != kk[i])return 0 ;
    }
    if(tot_k != len)return 0; ///匹配完后判断一下是否长度一样
    return 1;
}
bool ck(string s)  ///判断地址合法性
{
    int len = s.size();
    for(int i=0;i<len;i++){
        if((s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<='Z') || (s[i]>='0' && s[i] <='9')
            || (s[i] == '-') || (s[i] == '_') || (s[i] == '.') || (s[i] == '/') )continue;
        else return 0;
    }
    return 1;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>s[i]>>lyt[i];
        string k = "";
        int len = s[i].size();
        int tot = 0;
        for(int j=1;j<len;j++){ ///分割部分
            if(s[i][j] == '/'){
                C[i][++tot] = k;
                k = "";
            }
            else{
                k += s[i][j];
            }
        }
        if(s[i][len-1] != '/')C[i][++tot] = k;
        sz[i] = tot;
    }
    while(m--){
        string ss;
        cin>>ss;
        idx_p = -1;
        if(!ck(ss)){
            cout<<404<<endl;
        }
        int len = ss.size();
        tot_k = 0;
        string k = "";
        for(int j=1;j<len;j++){ ///分割查询
            if(ss[j] == '/'){
                kk[++tot_k] = k;
                k = "";
            }
            else{
                k += ss[j];
            }
        }
        if(ss[len-1] != '/')kk[++tot_k] = k;
        int idx = -1;
        for(int i=1;i<=n;i++){  ///逐一匹配
            int lb = s[i].size();
            if(C[i][sz[i]] != "<path>"){  ///第三细节 (40分)
                if(ss[len-1] == '/' && s[i][lb-1] != '/')
                    continue;
                if(ss[len-1] != '/' && s[i][lb-1] == '/')
                    continue;
            }
            tot_p = 0;
            if(check(i)){
                idx = i;break;
            }
        }
        if(idx == -1){
            cout<<404<<endl;
        }
        else{
            cout<<lyt[idx];
            for(int i=1;i<=tot_p;i++){
                cout<<" "<<ans[i];
            }
            int cnt = 0;
            if(idx_p != -1){
            cout<<" ";
                for(int i=0;i<len;i++){
                    if(cnt >= idx_p){
                        cout<<ss[i];
                    }
                    if(ss[i] == '/'){
                        cnt++;
                        continue;
                    }
                }
            }
            cout<<endl;
        }
    }
}
/*

5 5
/articles/2003/ special_case_2003
/articles/<int>/ year_archive
/articles/<int>/<int>/ month_archive
/articles/<int>/<int>/<str>/ article_detail
/static/<path> static_serve

/articles/2004
/articles/0002004/
/articles/1985/09/aloha/
/articles/hello/
/static/js/jquery.js

 */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值