题目的主要信息:
-
验证输入的密码是否符合要求,输入一组或者多组长度超过2的字符串,要求输出OK(符合要求)或者NG(不符合要求)
-
密码要求:
-
长度超过8位
-
包括大小写字母.数字.其它符号,以上四种至少三种
-
不能有相同长度大于2的子串重复
-
方法一:暴力验证
具体做法:
分三步依次检查上面的要求就行了。
-
首先检查输入的字符串长度,如果不大于8,输出NG,后面不用管;
-
准备一个长度为4的辅助数组,初始为0,遍历字符串,检查每种字符是否出现,如果出现则数组相应位置置为1,最后数组4个元素相加,如果小于3,还是输出NG,后面不用管;
-
最后我们要检查是否有相同长度大于2的字串重复,大于2,那我们找长度为3的重复子串就行了,因为大于3的也一定包含了这个3。两层遍历字符串,指针之间间隔三个,用substr函数截取两个下标开始的三位字符,检查是否相同,若是相同,也是NG。
最后经过上述步骤都不NG的,就是OK。
#include<iostream>
#include<string>
using namespace std;
int main(){
string s;
while(cin >> s){
if(s.length() <= 8){ //长度不超过不可行
cout << "NG" << endl;
continue;
}
int flag[4] = {0};
for(int i = 0; i < s.length(); i++){
if(s[i] >= 'A' && s[i] <= 'Z') //大写字母
flag[0] = 1;
else if(s[i] >= 'a' && s[i] <= 'z') //小写字母
flag[1] = 1;
else if(s[i] >= '0' && s[i] <= '9') //数字
flag[2] = 1;
else //其他符号
flag[3] = 1;
}
if(flag[0] + flag[1] + flag[2] + flag[3] < 3){ //符号少于三种
cout << "NG" << endl;
continue;
}
bool repute = false; //记录重复子串
for(int i = 0; i <= s.length() - 6; i++) //遍历检查是否有长度为3的相同的字串
for(int j = i + 3; j < s.length(); j++)
if(s.substr(i, 3) == s.substr(j, 3)){
repute = true;
break;
}
if(repute) //有重复
cout << "NG" << endl;
else
cout << "OK" << endl;
}
return 0;
}
复杂度分析:
- 时间复杂度:,为单次密码长度,验证重复子串两层循环遍历字符串
- 空间复杂度:,字符串s属于必要空间,flag数组只有常数个变量
方法二:正则表达式
具体做法:
不管是单独匹配小写字母、大写字母、数字、其他字符,还是匹配串中前后连续三个一样的字符,我们都可以用正则表达式。写出正则表达式以后,我们使用regex_search,只需要找到有可以匹配的,而不需要完全匹配。
#include<iostream>
#include<string>
#include<regex>
using namespace std;
int main(){
string s;
while(cin >> s){
if(s.length() <= 8){ //长度不超过不可行
cout << "NG" << endl;
continue;
}
string re[4] = { "[a-z]", "[A-Z]", "\\d", "[^a-zA-Z0-9]" }; //分别匹配小写字母、大写字母、数字、其他字符
int count = 0;
for (int i = 0; i < 4; i++) {
regex pattern(re[i]);
if (regex_search(s, pattern)) //只需要查找到,不要求完全匹配
count++;
}
if(count < 3){ //符号少于三种
cout << "NG" << endl;
continue;
}
regex pattern(".*(...)(.*\\1).*"); //匹配串前后连续3个字符一样的
if(regex_search(s, pattern))
cout << "NG" << endl;
else
cout << "OK" << endl;
}
return 0;
}
复杂度分析:
- 时间复杂度:,正则表达式匹配复杂度为
- 空间复杂度:,常数级空间,字符串s属于必要空间