201803-4 棋局評估

這道題當初卡了我不知道多少遍,每次動手想作一下CSP認證的第三道題,都從這道題開始,但每次都被卡住。直接是連題意都有點讀不懂,可是讀懂了以後就會發現,這道題除了特別繁瑣以外,好像也沒用到什麼很難的算法。c++

借鑑了這位大佬的思路:https://blog.csdn.net/xbb224007/article/details/79962425?utm_source=blogxgwz0算法

我沒發現比這個還簡潔的代碼,因此就學了一下這個思路,比較容易理解。數組

對這道題,我實際上是無從下手的。究其緣由,在於:1.字符串匹配的題目作的太少了,沒作幾道。2.不太會stringstream流操做,因此對複雜的字符串操做不夠靈活。3.數據結構沒想出來,不知道用什麼來存這麼多的字符串。數據結構

題目大意是這樣的,給出一連串匹配規則,以及一連串待匹配字符串。對每一個待匹配字符串,要拿每個規則匹配它,若是匹配成功,就輸出這個規則名稱,以及成功匹配的參數部分(即用題中的str、int、path成功匹配的部分,其餘的成功匹配不輸出);若是對全部規則都不匹配,就輸出404。函數

先開一個一維字符串數組,存放全部原始規則,再開一個二維字符數組,存放每個原始規則被'/'拆分後的部分。再開一個一維整型數組,存放每一條原始規則拆分後的部分數,再開一個記號數組,標記每一條原始數組是否爲'/'結尾。spa

以後開一個二重循環,對每一條待匹配語句都對每一條規則進行比較,若是有一個成立就跳出。匹配函數是一個模塊。對每個語句的匹配,都要拆分開來,一部分一部分匹配,這須要一個拆分函數;對 ,須要檢查這個串是不是數字,若是是數字,須要返回去掉前導0的串,這也是一個函數模塊。那麼總起來,包括main函數,一共有四個模塊,分開寫。 .net

下面是代碼,部分關鍵地方有註釋。其實很顯然,難就難在對字符串的拆分和匹配上了,數據結構想不出來,拆分不會,這題就是0分了。code

程序中有不少小細節,箇中巧妙之處,須要細細體會。blog

#include <bits/stdc++.h>
#define N 105
using namespace std;
string lim[N],lims[N][N],limname[N];    //lim是第i個規則字符串,lims是第i個規則字符串的拆分,limname是對應字符串的名字
string now,nows[N];                     //nows是當前被檢索字符串的拆分
bool isop[N],iso;                    //isop判斷規則末尾有無斜槓,iso判斷地址末尾有無斜槓
int limcnt[N],nowcnt;                   //limcnt計數規則的拆分後項數,nowcnt計數當前被檢索字符串的拆分後項數
void stcut(string ori,string cut[],bool& is,int&num);
bool match(int j,int nc,string& a);
string isnum(string s);
int main()  {
    int n,m;
    cin>>n>>m;
    for (int i=0;i<n;i++)   {
        cin>>lim[i]>>limname[i];
        stcut(lim[i],lims[i],isop[i],limcnt[i]);
    }
    for (int i=0;i<m;i++)   {
        cin>>now;iso=0;             //注意此處將iso置0
        stcut(now,nows,iso,nowcnt);
        string ans;
        int f=0;
        for (int j=0;j<n;j++)   {
            if (match(j,nowcnt,ans)) {
                string ss=limname[j]+ans;
                cout<<ss<<endl;
                f=1;break;
            }
        }
        if (f==0)   cout<<404<<endl;
    }
    return 0;
}

//nows是當前字符串,j是當前的斷定模塊序號,nc是當前字符串切分後的項數,a是可能的跟在標籤後面的答案字符串
bool match(int j,int nc,string& a)  {
    a="";
    int p1=0,p2=0;
    while (p1<nc&&p2<limcnt[j]) {
        if (nows[p1]==lims[j][p2])   ;
        else if (lims[j][p2]=="<int>")    {
            string st=isnum(nows[p1]);
            if (st=="") return 0;
            else    a+=' '+st;
        }
        else if (lims[j][p2]=="<path>") {
            a+=' '+nows[p1++];
            while (p1<nc)   a+='/'+nows[p1++];
            if (iso)    a+='/';
            return 1;
        }
        else if (lims[j][p2]=="<str>")  a+=' '+nows[p1];
        else return 0;
        p1++,p2++;
    }
    if (p1<nc||p2<limcnt[j])    return 0;
    if (isop[j]^iso)    return 0;
    return 1;
}

//ori是原始字符串,cut是切割後的分塊,is是判斷最後有無'/',num是切分後的項數
void stcut(string ori,string cut[],bool& is,int& num){
    int len=ori.size();
    string ss;
    num=0;
    if (ori[len-1]=='/')    is=1;
    for (int i=0;i<(int)ori.size();i++)
        if (ori[i]=='/')    ori[i]=' ';
    stringstream in(ori);
    while (in>>ss)    cut[num++]=ss;;
}

string isnum(string s)  {
    string ans="";
    int ok=0;
    for (int i=0;i<(int)s.size();i++)   {
        if (s[i]<'0'||s[i]>'9') return "";
        else if (ok||(s[i]>'0'&&s[i]<='9')) ans+=s[i],ok=1;
    }
    return ans;
}
相關文章
相關標籤/搜索