列表

详情


SG8. 伪正则表达式

描述

判断一个数字串是否匹配一个表达式,具体如下:
1)表达式m:一定不为空,只能由数字和“*”构成,其中的“*”表示匹配一个或多个“它前面所有非”*“的数字的和值除以10的余数”;“*”如果在最前面或其前面都是“*”,则只可以是任意一个数字。
2)数字串s:可能为空,只能由数字构成,不能包含其它字符。
3)是否匹配:匹配要求覆盖整个数字串s,而不是某一部分匹配。

解题要求:不能将m转写成标准正则表达式来解题,需要自己编程实现匹配算法。

注意,对应objc语言,系统里的@autoreleasepool {} 需要改写成如下形式
#import <Foundation/Foundation.h>
//strcmp
//NSString:
//- (NSArray<NSString *> *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
//- (unichar)characterAtIndex:(NSUInteger)index;
//- (NSString *)substringWithRange:(NSRange)range;

int main(int argc, const char * argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    //...
    //add your code
    //...
    [pool drain];
    return 0;
}

输入描述

见输入样例,其中最后一行的0表示结束输入

输出描述

YES:匹配

NO:不匹配

示例1

输入:

3
1*
11111
**1
121
**1
1221
0

输出:

YES
YES
NO

说明:

3表示case数有3个
case 1:1*是表达式,11111是数字串,*前面所有数字的和值除以10的余数为1,*表示匹配1个或1个以上的前面数字”1“,刚好“1111”符合匹配规则,所以,输出YES。
case 2:**1是表达式,121是数字串,第一个*在最前面,可以是任意数字,与“1”匹配;第二个“*”因为前面都是“*”,所以可以是任意一个数字,与“2”匹配。总体看,两者符合匹配规则,输出YES。
case 3:**1是表达式,1221是数字串,第一个*与“1”匹配,第二个*与“2”匹配,但只能匹配一个“2”,整体不符合匹配规则,所以,输出NO。

示例2

输入:

3
1*
11111
21*
2103
22*
22*
0

输出:

YES
NO
NO

说明:

3表示case数有3个
case 1:1*是正则表达式,11111是数字串,两者符合匹配规则,所以,输出YES。
case 2:21*是正则表达式,2103是数字串,*前面所有数字的和值除以10的余数为3,刚好“03”并不符合匹配规则,所以,输出NO。
case 3:22*是正则表达式,22*是数字串,但是因为其中包含了*这样的非数字字符,并不符合匹配规则,所以,输出NO。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 2ms, 内存消耗: 384KB, 提交时间: 2020-10-31

#include <bits/stdc++.h>
using namespace std;

string p,t;
bool dfs(int i, int j, int cur) {
	if (j == t.size()&&i == p.size())return true;
	if (i == p.size())return false;
	if (p[i] == t[j]) {
		return dfs(i + 1, j + 1, (cur + t[j] - '0') % 10);
	}else if (p[i] == '*') {
		return cur == t[j] - '0' ? dfs(i, j + 1, cur % 10) || dfs(i + 1, j + 1, cur % 10) : false;
	}
	return false;
}

void getNum() {
	if (t.size() < p.size()) {
		cout << "NO" << endl;
		return;
	}
	for (int i = 0; i < t.size(); ++i) {
		if (!(t[i] >= '0'&&t[i] <= '9')) {
			cout << "NO" << endl;
			return;
		}
	}
	int i = 0;
	for (; i < p.size(); ++i) {
		if (p[i] != '*')break;
	}
	t = t.substr(i);
	p = p.substr(i);
	if ((t == ""&&p != "") || (t != ""&&p == "")) {
		cout << "NO" << endl;
		return;
	}
	if (dfs(0, 0, 0)) {
		cout << "YES" << endl;
	}
	else {
		cout << "NO" << endl;
	}
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	string str;
	getline(cin, str);
	int n = stoi(str);
	while (n--) {
		getline(cin,p);
		getline(cin,t);
		getNum();
	}
}

C++ 解法, 执行用时: 2ms, 内存消耗: 484KB, 提交时间: 2019-11-09

#include <bits/stdc++.h>
using namespace std;

string p,t;
bool dfs(int i, int j, int cur) {
	if (j == t.size()&&i == p.size())return true;
	if (i == p.size())return false;
	if (p[i] == t[j]) {
		return dfs(i + 1, j + 1, (cur + t[j] - '0') % 10);
	}else if (p[i] == '*') {
		return cur == t[j] - '0' ? dfs(i, j + 1, cur % 10) || dfs(i + 1, j + 1, cur % 10) : false;
	}
	return false;
}

void getNum() {
	if (t.size() < p.size()) {
		cout << "NO" << endl;
		return;
	}
	for (int i = 0; i < t.size(); ++i) {
		if (!(t[i] >= '0'&&t[i] <= '9')) {
			cout << "NO" << endl;
			return;
		}
	}
	int i = 0;
	for (; i < p.size(); ++i) {
		if (p[i] != '*')break;
	}
	t = t.substr(i);
	p = p.substr(i);
	if ((t == ""&&p != "") || (t != ""&&p == "")) {
		cout << "NO" << endl;
		return;
	}
	if (dfs(0, 0, 0)) {
		cout << "YES" << endl;
	}
	else {
		cout << "NO" << endl;
	}
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	string str;
	getline(cin, str);
	int n = stoi(str);
	while (n--) {
		getline(cin,p);
		getline(cin,t);
		getNum();
	}
}

C++ 解法, 执行用时: 2ms, 内存消耗: 524KB, 提交时间: 2020-10-31

#include <bits/stdc++.h>
using namespace std;

string p,t;
bool dfs(int i, int j, int cur) {
	if (j == t.size()&&i == p.size())return true;
	if (i == p.size())return false;
	if (p[i] == t[j]) {
		return dfs(i + 1, j + 1, (cur + t[j] - '0') % 10);
	}else if (p[i] == '*') {
		return cur == t[j] - '0' ? dfs(i, j + 1, cur % 10) || dfs(i + 1, j + 1, cur % 10) : false;
	}
	return false;
}

void getNum() {
	if (t.size() < p.size()) {
		cout << "NO" << endl;
		return;
	}
	for (int i = 0; i < t.size(); ++i) {
		if (!(t[i] >= '0'&&t[i] <= '9')) {
			cout << "NO" << endl;
			return;
		}
	}
	int i = 0;
	for (; i < p.size(); ++i) {
		if (p[i] != '*')break;
	}
	t = t.substr(i);
	p = p.substr(i);
	if ((t == ""&&p != "") || (t != ""&&p == "")) {
		cout << "NO" << endl;
		return;
	}
	if (dfs(0, 0, 0)) {
		cout << "YES" << endl;
	}
	else {
		cout << "NO" << endl;
	}
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	string str;
	getline(cin, str);
	int n = stoi(str);
	while (n--) {
		getline(cin,p);
		getline(cin,t);
		getNum();
	}
}

C++ 解法, 执行用时: 3ms, 内存消耗: 376KB, 提交时间: 2020-07-15

#include <iostream>
#include <string>
 
using namespace std;
//s为数字串,p为表达式,sum为'*'前面所有数字和
bool getP(string s, string p,int sum)
{
    int m=s.length();
    int n=p.length();
    int i=0,j=0;
    int flag=false;        //‘*’是否已经匹配过
    while(i<m && j<n)
    {
        if(s[i] >'9' || s[i] <'0')       //字符串非法
            return false;
        if(p[j] !='*')                 //统计数字余数和
            sum = (sum+ p[j]-'0')%10;
        if(s[i] == p[j])              //正常匹配
        {
            i++;j++;
        }
        else if(p[j] == '*')          //'*'匹配
        {
            if(j==0 ||( j>=1 && p[j-1] == '*') )      //只能匹配一个任意字符的‘*’
            {
                i++; 
                j++;
                continue;
            }
            if(flag == true)           //可匹配多个的'*'已匹配过
            {
                if( (sum+'0') == s[i] )   //两种选择,继续匹配或者匹配下一个
                {
                    if( getP(s.substr(i,s.length()-i),p.substr(j+1,p.length()-j-1),sum) ==true )
                        return true;   //成功直接返回
                    i++;
                }
                else           //匹配失败,匹配下一个
                {
                    flag=false;
                    j++;
                }
            }
            else                  //'*'未匹配
            {
                if((sum+'0') == s[i])   //匹配成功
                {
                    flag=true;
                    i++;    
                }
                else                   //匹配失败
                    return false;
            }
        }
        else
            return false;     //匹配失败   
    }    
    if(j>0 && p[j] =='*' &&  p[j-1] !='*' )   //最后剩一个匹配多个‘*’
        j++;
    if(i==m && j==n)      //匹配完成
        return true;
    else
        return false ; 
}
int main(){
    int n;
    cin >> n;
    string s,p;
    getline(cin,p);        //因为存在空串,使用getline,不用cin>>,这里把n后面的换行读取掉
    while(n--)
    {
        getline(cin,p);   //因为存在空串,使用getline,
        getline(cin,s);   //因为存在空串,使用getline,
        bool f=getP(s,p,0);
        if(f)
            cout<<"YES"<<endl;
        else   
            cout<<"NO"<<endl;
    }
    cin>>n;
    return 0;
}

C++ 解法, 执行用时: 3ms, 内存消耗: 380KB, 提交时间: 2020-11-01

#include <bits/stdc++.h>
using namespace std;

string p,t;
bool dfs(int i, int j, int cur) {
	if (j == t.size()&&i == p.size())return true;
	if (i == p.size())return false;
	if (p[i] == t[j]) {
		return dfs(i + 1, j + 1, (cur + t[j] - '0') % 10);
	}else if (p[i] == '*') {
		return cur == t[j] - '0' ? dfs(i, j + 1, cur % 10) || dfs(i + 1, j + 1, cur % 10) : false;
	}
	return false;
}

void getNum() {
	if (t.size() < p.size()) {
		cout << "NO" << endl;
		return;
	}
	for (int i = 0; i < t.size(); ++i) {
		if (!(t[i] >= '0'&&t[i] <= '9')) {
			cout << "NO" << endl;
			return;
		}
	}
	int i = 0;
	for (; i < p.size(); ++i) {
		if (p[i] != '*')break;
	}
	t = t.substr(i);
	p = p.substr(i);
	if ((t == ""&&p != "") || (t != ""&&p == "")) {
		cout << "NO" << endl;
		return;
	}
	if (dfs(0, 0, 0)) {
		cout << "YES" << endl;
	}
	else {
		cout << "NO" << endl;
	}
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	string str;
	getline(cin, str);
	int n = stoi(str);
	while (n--) {
		getline(cin,p);
		getline(cin,t);
		getNum();
	}
}

上一题