全是套路——字符串通配符


華為OJ的題:

問題描述:在計算機中,通配符一種特殊語法,廣泛應用於文件搜索、數據庫、正則表達式等領域。現要求各位實現字符串通配符的算法。
要求:
實現如下2個通配符:
*:匹配0個或以上的字符(字符由英文字母和數字0-9組成,不區分大小寫。下同)
?:匹配1個字符


輸入:
通配符表達式;
一組字符串。


輸出:
返回匹配的結果,正確輸出true,錯誤輸出false

在OJ里面是初級題。最近腦子很笨,反應不過來。也是在網上看了思想之后才編出來的。

具體思想:

1.由於*可以代替任意字符,所以*先要忽略

2.?可以代替一個字符,所以將它考慮到當中

3.以*為分隔符來分割字符串,現在字符串是一系列的字符。如果第一個字符跟整體匹配上了,下一個字符接着上一個匹配的末尾繼續匹配,以此類推,都匹配成功就算匹配成功。

4.字符串的匹配因為涉及到?,不能直接用string的find。所以用kmp算法。

KMP具體來說,就是在原字符串中找到第一個與匹配字符串相同的字母,然后依次匹配若成功則返回,若失敗,則記錄失敗的位置,下次從失敗的位置開始匹配。這樣可以提高效率。

注:對於?匹配其實沒有那么麻煩,只有在if語句中加上一個||就可以了如果匹配字符串中的那個位是?就默認匹配成功。

上代碼:

#include <stdio.h>
#include <iostream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

char daxie(char c)
{
    if (c >= 'A'&&c <= 'Z')
    {
        c = c - 'A' + 'a';
    }
    return c;
}

int pipei(string S, string T)
{
    int index = 0;
    for (int i = index; i < S.size(); i++)
    {
        if (S[i] == T[0]||T[0]=='?')
        {
            int k;
            for (k = 0; k < T.size() && k+i <S.size() ; k++)
            {
                if (S[k+i] == T[k]||T[k]=='?')
                {

                }
                else
                {
                    index = k + i;
                    break;
                }
            }
            if (k == T.size() )
            {
                return i;
            }
        }
    }
    return -1;
}

int main()
{
    string str1, str2;
    while (cin >> str1>>str2)
    {
        for (int i = 0; i < str1.size(); i++)
        {
            str1[i] = daxie(str1[i]);
        }
        for (int i = 0; i < str2.size(); i++)
        {
            str2[i] = daxie(str2[i]);
        }
        vector<string> a;
        int pos = -1;
        while ((pos = str1.find('*')) != string::npos)
        {
            a.push_back(str1.substr(0, pos));
            str1 = str1.erase(0, pos + 1);
        }
        a.push_back(str1);
        for (int i = 0; i < a.size(); i++)
        {
            if (a[i] == "")
            {
                a.erase(a.begin() + i, a.begin() + i + 1);
            }
        }
        int i;
        for (i = 0; i < a.size(); i++)
        {
            int pos = -1;
            if ((pos = pipei(str2, a[i])) < 0)
            {
                cout << "false" << endl;
                break;
            }
            else
            {
                str2 = str2.erase(0, pos + a[i].size());
            }
        }
        if (i == a.size())
        {
            cout << "true" << endl;
        }
        
        int kk = 0;
    }

    return 0;

}

注意:此代碼是有些問題的。比如你輸入*,按道理是都能匹配的,但是有字符串分割沒有成功,所以會失敗,但是就不更改了。

還有一個問題,雖然華為的系統沒有檢測,但是還是不能忽略的。

*只能代表數字和字母,並不能匹配除這以外的。(可能是華為的測試樣例也沒有考慮吧)

所以如果輸入*.* 和...也會匹配成功,這是不嚴謹的。所以說匹配的時候,在跳過的那幾個串中要檢測有沒有*不能替代的字符,如果算不匹配。


免責聲明!

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



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