暴力枚举解法,先找出所有的前缀,再按长度从大到小遍历,判断该前缀能否同时整除str1和str2,能则直接返回,否则继续遍历。若所有前缀都不符合,返回空字符串。
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
int i = 0, j = 0;
int m = str1.size(), n = str2.size();
vector<string> prefix_vec;
prefix_vec.reserve(max(m, n));
string prefix = "";
while (i < m && j < n && str1[i] == str2[j]) {
prefix += str1[i];
prefix_vec.push_back(prefix);
i++;
j++;
}
for (auto it = prefix_vec.rbegin(); it != prefix_vec.rend(); ++it) {
bool flag1 = is_valid_prefix(*it, str1);
if (!flag1) {
continue;
}
bool flag2 = is_valid_prefix(*it, str2);
if (!flag2) {
continue;
}
return *it;
}
return "";
}
bool is_valid_prefix(string& prefix, string& target){
int length_pre = prefix.size();
int length_tar = target.size();
if (length_tar % length_pre != 0) {
return false;
}
string tmp = "";
for (int i = length_pre; i < length_tar; i++) {
tmp += target[i];
if (tmp.size() == length_pre){
if (tmp != prefix) {
return false;
}
tmp.clear();
}
}
return true;
}
};
优化思路:先求两个字符串长度的最大公约数x,然后直接判断长度为x的前缀是否满足要求。以下为c++的求最大公约数函数:
// 使用欧几里得算法计算最大公约数
int gcd(int a, int b) {
while(b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
原理:欧几里得算法,两个整数的最大公约数等于其中较小数和两数相除余数的最大公约数。