华为机试—密码验证合格程序
题目
你需要书写一个程序验证给定的密码是否合格。
合格的密码要求:
- 长度超过 8 位
- 必须包含大写字母、小写字母、数字、特殊字符中的至少三种
- 不能分割出两个独立的、长度大于 2 的连续子串,使得这两个子串完全相同;更具体地,如果存在两个长度大于 2 的独立子串 s1,s2 ,使得 s1=s2 ,那么密码不合法。
子串为从原字符串中,连续的选择一段字符(可以全选、可以不选)得到的新字符串。
可见字符集为 ASCII 码在 33 到 126 范围内的可见字符。
示例
若密码合格,输出 OK ,否则输出 NG 。
示例1
输入:
021Abc9000 021Abc9Abc1 021ABC9000 021$bc9000 021Abc1111输出:
OK NG NG OK OK说明:对于第二组测试数据,"Abc9Abc1" 中存在两个长度大于 2 的独立子串 "Abc"。
对于第三组测试数据,仅包含大写字母和数字,不满足条件。示例2
输入:
Abc1@ A1@ababa@1A输出:
NG OK说明:对于第一组测试数据,长度不足 8 位,不满足条件。
分析
哈希表+枚举
字符类型检查:在 hasThreeTypes
函数中,使用了遍历算法。通过遍历密码字符串中的每个字符,利用字符处理函数(如 std::isupper
、std::islower
、std::isdigit
)对字符进行分类判断,以确定密码中是否包含大写字母、小写字母、数字和特殊字符。
重复子串检查:在 hasRepeatedSubstring
函数中,结合了子串枚举和哈希表(std::unordered_set
)的算法思想。首先,通过两层循环枚举所有可能的子串长度和起始位置,然后使用 std::unordered_set
来存储已经出现过的子串。在遍历过程中,如果发现某个子串已经存在于哈希表中,就说明存在重复子串。
时间复杂度:O(),
是字符串的长度
空间复杂度:O()
#include <iostream>
#include <string>
#include <unordered_set>
#include <cctype>
// 检查密码是否包含至少三种类型的字符
bool hasThreeTypes(const std::string& password) {
bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;
for (char c : password) {
if (std::isupper(c)) hasUpper = true;
else if (std::islower(c)) hasLower = true;
else if (std::isdigit(c)) hasDigit = true;
else if (c >= 33 && c <= 126) hasSpecial = true;
}
int typeCount = 0;
if (hasUpper) ++typeCount;
if (hasLower) ++typeCount;
if (hasDigit) ++typeCount;
if (hasSpecial) ++typeCount;
return typeCount >= 3;
}
// 检查密码中是否存在两个长度大于 2 的相同独立连续子串
bool hasRepeatedSubstring(const std::string& password) {
int n = password.length();
for (int len = 3; len <= n / 2; ++len) {
std::unordered_set<std::string> seen;
for (int i = 0; i <= n - len; ++i) {
std::string sub = password.substr(i, len);
if (seen.find(sub) != seen.end()) {
return true;
}
seen.insert(sub);
}
}
return false;
}
// 验证密码是否合格
bool isPasswordValid(const std::string& password) {
// 检查长度是否超过 8 位
if (password.length() <= 8) return false;
// 检查是否包含至少三种类型的字符
if (!hasThreeTypes(password)) return false;
// 检查是否存在两个长度大于 2 的相同连续子串
if (hasRepeatedSubstring(password)) return false;
return true;
}
int main() {
std::string s;
while (std::getline(std::cin, s)) {
if (isPasswordValid(s)) {
std::cout << "OK" << std::endl;
} else {
std::cout << "NG" << std::endl;
}
}
return 0;
}