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


    华为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;
    
    }

    注意:此代码是有些问题的。比如你输入*,按道理是都能匹配的,但是有字符串分割没有成功,所以会失败,但是就不更改了。

    还有一个问题,虽然华为的系统没有检测,但是还是不能忽略的。

    *只能代表数字和字母,并不能匹配除这以外的。(可能是华为的测试样例也没有考虑吧)

    所以如果输入*.* 和...也会匹配成功,这是不严谨的。所以说匹配的时候,在跳过的那几个串中要检测有没有*不能替代的字符,如果算不匹配。

  • 相关阅读:
    Linux 工具命令
    Js的一些工具方法
    使用curl测试网络通信
    python 创建XML
    Nginx 使用Lua脚本
    lua 安装cjson
    3对象和类_动手动脑
    10.5
    10.4动手动脑
    10.2
  • 原文地址:https://www.cnblogs.com/wyc199288/p/5647635.html
Copyright © 2020-2023  润新知