惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
罗磊的独立博客
S
SegmentFault 最新的问题
D
Docker
博客园 - 司徒正美
雷峰网
雷峰网
V
Visual Studio Blog
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
MyScale Blog
MyScale Blog
MongoDB | Blog
MongoDB | Blog

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
HDU 6170.Two strings|OhYee 博客
2017-08-22 · via OhYee 博客

题目

{% fold 点击显/隐题目 %}

Giving two strings and you should judge if they are matched. The first string contains lowercase letters and uppercase letters. The second string contains lowercase letters, uppercase letters, and special symbols: “.” and “\*”. . can match any letter, and * means the front character can appear any times. For example, “a.b” can match “acb” or “abb”, “a\*” can match “a”, “aa” and even empty string. ( “\*” will not appear in the front of the string, and there will not be two consecutive “\*”.

The first line contains an integer T implying the number of test cases. (T≤15) For each test case, there are two lines implying the two strings (The length of the two strings is less than 2500).

For each test case, print “yes” if the two strings are matched, otherwise print “no”.

3 aa a\* abb a.\* abb aab

yes yes no

{% endfold %}

题解

正则表达式

基本上可以在读题都一半的时候确定是正则表达式的问题
通常来说,这种问题一半会使用AC自动机来解答,不过其实可以试一下C++11的正则表达式库的

首先确定题意的时候可以发现,这里和标准的正则表达式语句存在一些不同
.* 在标准的正则表达式中是匹配任意字符串,而这里是匹配任意的连续字符串
相当于 (.)?\1*

当然,还需要考虑*可以匹配0次,但是这是正则表达式本身就有的语法
因此,简单思路就是先把 .* 替换成 (.)?\1* (在源码里要写成(.)?\\1*)
然后直接匹配即可
相应部分的代码如下
具体实现代码见正则表达式源码

需要特别注意的是,虽然同样是无脑用库,但是Java会超时
另外C++11的Regex库存在的bug比较多,只有比较简单的匹配才能放心使用
比如aba匹配abababa是无法得到3的,无法使用类似这样的(?=(aba))零宽断言语法来实现(其他语言可以)

动态规划

按照动态规划的思路,很容易得到dp[i][j]表示字符串a的前i个字符和字符串b的前j的字符能否匹配
假如我们要匹配 aaaaaaab*a*

对于第一个位置(最左上角),显然当两者相等的时候为true
其同一行已经没有能够匹配的了
第二行可以发现b不等于a全部都是false
第三行的*可以将上一行的b匹配0次,这时,当前位置能否匹配成功取决于它上面的上面是否能匹配
第四行有aa相同,位置能否匹配取决于其左上角的能否匹配
第五行的*可以匹配任意长度,匹配两个时候相当于该位置取决于上面能否匹配;匹配更多个的时候相当于只要其对应的a中的字符和它左面的相同,就可以将左面能否匹配的状态传递过来

另外,.可以看作一个普通字符,只是能和所有的字符都匹配
综上所述,总共只包含很少的状态转移条件

  • 串内容相同(或者存在'.'或者为第一个位置):
    dp[i][j] |= dp[i-1][j-1]
  • 匹配到*:
    dp[i][j] |= dp[i][j-2] | dp[i][j-1]
  • 匹配到*,并且当前位置和其左面的字符相同:
    dp[i][j] |= dp[i-1][j]

这样就可以写出基本的dp框架了
然后就会发现我们漏掉了一个特殊情况
bbbbbb匹配a*b*
由于开始位置匹配失败,导致后面所有位置都无法为true
只有b[1]=='*'的时候才会导致这个错误
相当于特殊情况下的状态转移1
其条件如下: 串内容相同或者存在.,同时i=0,b[1]='*'

这样就可以写出完整的状态转移方程了

代码

正则表达式

{% fold 点击显/隐代码 %}```cpp Two strings https://github.com/OhYee/sourcecode/tree/master/ACM 代码备份
#include
#include
#include
using namespace std;

void string_replace(string &s1, const string &s2, const string &s3) {
string::size_type pos = 0;
string::size_type a = s2.size();
string::size_type b = s3.size();
while ((pos = s1.find(s2, pos)) != string::npos) {
s1.replace(pos, a, s3);
pos += b;
}
}

int main() {
cin.tie(0);
cin.sync_with_stdio(false);
int T;
cin >> T;

while (T--) {
    string text, re;

    cin >> text >> re;
    //cout << text << endl << re << endl;
    string_replace(re, ".*", "(.)?\\1*");
    // cout << text <<" "<< re << endl;

    regex e(re);
    cout << (regex_match(text, e) ? "yes" : "no") << endl;
}

return 0;

}

{% endfold %}

## 动态规划
{% fold 点击显/隐代码 %}```cpp Two strings https://github.com/OhYee/sourcecode/tree/master/ACM 代码备份
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int maxn = 3505;

char a[maxn], b[maxn];
bool dp[maxn][maxn];

int main() {
    cin.tie(0);
    cin.sync_with_stdio(false);

    int T;
    cin >> T;

    // scanf("%d", &T);
    // getchar();
    while (T--) {
        cin >> a >> b;
        // scanf("\n%[^\n]\n%[^\n]", a, b);
        // fgets(a,maxn,stdin);
        // fgets(b,maxn,stdin);

        memset(dp, false, sizeof(dp));

        // printf("%d\na:%s\nb:%s\n",T, a, b);
        int n = strlen(a);
        int m = strlen(b);

        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j) {
                // 第一个位置
                if ((a[i] == b[j] || b[j] == '.') && i == 0 && j == 0)
                    dp[i][j] |= true;
                // 从左上角转移过来
                if ((a[i] == b[j] || b[j] == '.') && i > 0 && j > 0)
                    dp[i][j] |= dp[i - 1][j - 1];
                // 特判
                if ((a[i] == b[j] || b[j] == '.') && b[1] == '*' && i == 0)
                    dp[i][j] = true;
                // * 匹配
                // 从上面的上面转移过来(匹配0个)
                //从上面转移过来(匹配1个)
                if (b[j] == '*')
                    dp[i][j] |= (j >= 2 ? dp[i][j - 2] : 0) |
                                (j >= 1 ? dp[i][j - 1] : 0);
                // 从左面转移过来(*往后续)
                if (b[j] == '*' && i >= 1 && a[i - 1] == a[i])
                    dp[i][j] |= dp[i - 1][j];
            }

        // for (int i = 0; i < n; ++i) {
        //     for (int j = 0; j < m; ++j)
        //         printf("%d ", dp[i][j]);
        //     printf("\n");
        // }
        // printf("%s\n", (dp[n - 1][m - 1] ? "yes" : "no"));
        cout << (dp[n - 1][m - 1] ? "yes" : "no") << endl;
    }
    return 0;
}

{% endfold %}