在Linux Shell命令下通配符’‘表示0个或多个字符, 现编写一段代码实现通配符’‘的功能,注意只需要实现’*’, 不用实现其他通配符。
输入描述:
第一行输入通配字符串
第二行输入要匹配查找的字符串
输出描述:
输出所有匹配的字串起始位置和长度,每行一个匹配输出
如果不匹配,则输出 -1 0
如果有多个按照起始位置和长度的正序输出。
输入例子1:
shopee*.com
shopeemobile.com
输出例子1:
0 16
例子说明1:
0 起始位置,16长度
输入例子2:
*.com
shopeemobile.com
输出例子2:
0 16
1 15
2 14
3 13
4 12
5 11
6 10
7 9
8 8
9 7
10 6
11 5
12 4
输入例子3:
o*m
shopeemobile.com
输出例子3:
2 5
2 14
7 9
14 2
#include <iostream>
#include <string>
using namespace std;
//只考虑一个 * 的情况case通过率为77.78%
int main() {
string pattern;
string str;
cin >> pattern >> str;
int len1 = pattern.length();
int len2 = str.length();
int someMatch = false;
if(pattern[0] == '*') {
if(pattern.length() > 1) {
int idx0 = 1;
char next = pattern[idx0];
int pos = 0;
int pos1 = str.find_first_of(next, pos);
while(pos1 != str.npos) {
int idx1 = pos1;
while(idx0 < len1 && idx1 < len2) {
if(pattern[idx0] == str[idx1]) {
idx0++;
idx1++;
} else {
break;
}
}
if(idx0 == len1) {
someMatch = true;
for(; pos <= pos1; pos++) {
cout << pos << " " << idx1-pos << endl;
}
}
idx0 = 1;
pos1 = str.find_first_of(next, pos1+1);
}
}
else { //只有一个 * ,通吃
//FIX ME
someMatch = true;
for(int i = 0; i < len2; i++) {
for(int j = i; j < len2; j++) {
cout << i << " " << j-i+1 << endl;
}
}
}
}
else { //首字母不是 *
int i = 0;
int start = -1;
for(int j = 0; j < len2; ++j) {
if(str[j] == pattern[i]) {
if(start == -1) {
start = j;
//cout << "find start " << start << endl;
}
i++;
//j++;
}
else if(pattern[i] == '*') {
int idx0 = i+1;
char next = pattern[idx0];
int pos = start;
int pos1 = str.find_first_of(next, start);
if(start == 14) {
//cout << "start " << start << ", next " << next << ", pos1 " << pos1 << endl;
}
while(pos1 != str.npos) {
int idx1 = pos1;
while(idx0 < len1 && idx1 < len2) {
if(pattern[idx0] == str[idx1]) {
idx0++;
idx1++;
}
else if(pattern[idx0] == '*') {
if(idx0+1 < len1) {
next = pattern[idx0+1];
pos1 = str.find_first_of(next,idx1);
idx0++;
idx1 = pos1;
}
}
else {
break;
}
}
if(idx0 == len1) {
someMatch = true;
cout << start << " " << idx1 - start << endl;
}
idx0 = i+1;
pos1 = str.find_first_of(next, pos1+1);
}
i = 0;
j = start + 1;
start = -1;
}
}
}
if(!someMatch) {
cout << -1 << " " << 0 << endl;
}
}
上面非递归版本的代码太繁琐(是可以优化代码的)
但是用递归来解这一题,代码相当简洁
#include <string>
#include <iostream>
#include <set> //需要使用有序的集合
using namespace std;
set<int> matchedPos;
void ExgrexMatch(string& pattern, int pos1, string& str, int pos2) {
if(pos1 == pattern.length()) { //str[j:pos2) 是匹配的
matchedPos.insert(pos2);
}
if(pos2 == str.length()) { //str结束
return;
}
if(pattern[pos1] == str[pos2]) { //匹配1个
ExgrexMatch(pattern, pos1+1, str, pos2+1);
}
else if(pattern[pos1] == '*') {
ExgrexMatch(pattern, pos1+1, str, pos2); //*匹配0个字符
ExgrexMatch(pattern, pos1+1, str, pos2+1); //*匹配1个字符
ExgrexMatch(pattern, pos1, str, pos2+1); //*匹配多个字符
}
else { // pattern[pos1] != '*' && pattern[pos1] != str[pos2]
return; //此路不匹配
}
}
int main1() {
string pattern, str;
cin >> pattern >> str;
int len1 = pattern.length();
int len2 = str.length();
bool someMatched = false;
for(int j = 0; j < len2; j++) {
if(str[j] == pattern[0] || pattern[0] == '*') {
ExgrexMatch(pattern, 0, str, j);
if(!matchedPos.empty()) {
someMatched = true;
for(auto pos : matchedPos) {
if(pos > j) { //*匹配0个字符的时候,pos-j为0,
//此时不应输出
cout << j << " " << pos - j << endl;
}
}
matchedPos.clear(); //清除开始下一轮
}
}
}
if(!someMatched) {
cout << -1 << " " << 0 << endl;
}
return 0;
}