ACM C++ 正则表达式使用简明指南
前言
前排提示!!!
这里的正则表达式只用来竞赛!!!!
只谈论正则函数的使用方法,不涉及正则表达式的基础使用方法。
尽管 C++ 的 正则表达式一直为人所诟病,一般人都会推荐你去使用boost的正则,但是ACM竞赛里显然是不能使用boost库的……
据说 C 的正则比 boost 的正则都要快,然而我不会……自然得觉得 C++ 会好用点吧。关于 C 的以后学。
正则表达式类 regex , 头文件即 regex。
三个核心函数
C++ 的正则库有三个常用函数,也是核心函数,分别是regex_match,regex_replace,regex_search
具体见下。我在这里只介绍在ACM里常用的一两个用法,具体了解还请点开各自的官方文档链接,上面有实例代码,非常好懂。
regex_match
regex_match 用来将正则表达式与整个字符串进行匹配,返回一个布尔值,如果匹配成功,返回true,反之,返回false。当然有很多附加功能,用一个match_result 记录匹配,或者各种选项标号什么还是得看上面的链接。
一个常用的方法就是直接regex_match( des , reg )
其中 des 表示待匹配字符串,reg为正则表达式,必须是 regex类。
regex_replace
regex_replace 是用来将所有正则表示匹配到的所有子串,替换成自定义子串。
一个常用的方法是 regex_replace( des,reg,rep )
其中 des 表示待匹配字符串,reg为正则表达式,必须是 regex 类,rep 为你想要替换成的字符串。
regex_search
regex_search 与 regex_match 类似但略有不同,regex_match 是对字符串进行全词匹配,而regex_search是对这个词进行局部查找。
这个函数,官方文档上貌似只给了一个实例。
这个实例也是我们常用的方法 regex_search( des,mac,reg )
其中,des为待匹配字符串,mac为结果集合,这个结果集合有点讲究,如果字符串是 string 类,那么我们与之对应必须是 smatch 类,如果是 字符数组,则为 cmatch 类。这个可以在 regex_match的实例代码中看到。reg则是我们的正则表达式,必须是regex类。
两个例题
HDU 1039 Easier Done Than Said?
题意:
让你判断一个字符串是否可被接受。接受条件有:
- 必须存在一个元音字符
- 不能存在连续三个都是元音字符或者三个都是非元音字符
- 不能出现除了 ee 或者是 oo 以外的连续字符子串
思路:
建立三个正则表达式,对其全局匹配与判断:
.*[aeiou]+.*
.*([aeiou]{3}|[^aeiou]{3}).*
.*([^eo])\\1.*
AC Code
#include <bits/stdc++.h>
using namespace std;
string des;
int main()
{
regex reg1(".*([aeiou]{3}|[^aeiou]{3}).*");
regex reg2(".*[aeiou]+.*");
regex reg3(".*([^eo])\\1.*");
while (cin >> des) {
if (des == "end")
break;
if (!regex_match(des, reg1) && regex_match(des, reg2) && !regex_match(des, reg3))
cout << "<" + des << "> is acceptable." << endl;
else
cout << "<" + des << "> is not acceptable." << endl;
}
return 0;
}
HDU 6170 Two strings
题意:
给你两个字符串,问你字符匹配。
其中第二个字符串可以转化,.
可以转化为单个任意字符,*
必须和前面一个字符相组合,表示前面一个字符可以出现任意次。
.*
只能表示任意相同字符的字符串,不能表示任意字符串。
思路:
北邮出的弱数据合集之一。淦。其实这道题用正则写起来不是很困难,但是给我栈溢出了,少考虑一种情况就能AC。
当然再少考虑一种情况还能AC,笑尿。
我想的正解但是栈溢出的是 (.?)\\k*
其中k是需要累加的。
但是 (.)\\k*
就过了,这是不符合题意的 比如 aabb
与 aa.*bb
还有的更荒唐是 (.)\\1*
随便那一对 比如 aabbccdd
与 aa.*cc.*
就不对了。
有一种写法是对的,就是吧 .*
换成(a*|b*|c*|d*)……
,个人认为这是对的,但却是无法容忍的!!!
但还是拿上AC代码吧。
#include <bits/stdc++.h>
using namespace std;
char tmp[20];
int main()
{
int T;
cin >> T;
while (T--) {
string pattern, buf, des;
cin >> des >> buf;
int len = buf.length();
for (int i = 0, k = 0; i < len; i++)
if (buf[i] == '.' && buf[i + 1] == '*') {
sprintf(tmp, "(.)\\%d*",++k);
pattern += tmp;
i++;
} else
pattern += buf[i];
regex reg(pattern);
bool judge = regex_match(des, reg);
puts(judge ? "yes" : "no");
}
return 0;
}