Greatest Common Divisor Strings
// https://leetcode.com/problems/greatest-common-divisor-of-strings
/*
For two strings s and t, we say "t divides s" if and only if s = t + ... + t (i.e., t is concatenated with itself one or more times).
Given two strings str1 and str2, return the largest string x such that x divides both str1 and str2.
Ex1:
Input: str1 = "ABCABC", str2 = "ABC"
Output: "ABC"
Ex2:
Input: str1 = "ABABAB", str2 = "ABAB"
Output: "AB"
Ex3:
Input: str1 = "LEET", str2 = "CODE"
Output: ""
*/
#include <string>
#include <cassert>
#include <iostream>
using namespace std;
// Time complexity: O(min(m, n)*(m+n)), Space complexity: O(min(m, n))
bool validGCD(string str1, string base) {
int m = str1.size();
int d = base.size();
if (m % d != 0) {
return false;
}
string output = "";
for (int i = 0; i < m/d; i++) {
output += base;
}
return output == str1;
}
string gcdOfStrings(string str1, string str2) {
int m = str1.size();
int n = str2.size();
string minStr = m < n ? str1 : str2;
for (int i = min(m, n); i > 0; i--) {
string base = minStr.substr(0, i);
if (validGCD(str2, base) && validGCD(str1, base)) {
return base;
}
}
return "";
}
// 奇技淫巧
/*
Intuition: If str1 + str2 != str2 + str1, there is no solution.
Regarding the largest string x, why gcd of str1 and str2 size is the answer?
Consider str1 = "ABCABCABC" and str2 = "ABCABC". The lengths are 9 and 6, respectively. The GCD is 3, which corresponds to the "ABC" substring that, when repeated, can form both str1 and str2.
Let's see some other examples:
For str1 = "ABABAB" and str2 = "ABAB", the lengths are 6 and 4, respectively. The GCD is 2, which corresponds to the "AB" substring.
Proof of Correctness:
Let str1 have length m and be represented as m * x (repeated x, m times). Similarly, let str2 have length n and be n * x (repeated x, n times).
If m > n, then the GCD(m, n) must divide both m and n. Therefore, we can form a string z of length GCD(m, n) that divides both m and n, and this will be the greatest such string.
For example, let G = gcd(m, n), then m = G * k1 and n = G * k2 for some integers k1 and k2. It implies str1 can be represented as (x[0:G] * k1) and str2 can be represented as (x[0:G] * k2). Hence x[0:G] is the largest common divisor string.
*/
// Time complexity: O(m+n), Space complexity: O(m+n)
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a%b);
}
string gcdOfStringsWithMath(string str1, string str2) {
if (str1 + str2 != str2 + str1) {
return "";
}
return str1.substr(0, gcd(str1.size(), str2.size()));
}
int main() {
string str1 = "ABCABC";
string str2 = "ABC";
assert(gcdOfStrings(str1, str2) == "ABC");
assert(gcdOfStringsWithMath(str1, str2) == "ABC");
str1 = "ABABAB";
str2 = "ABAB";
assert(gcdOfStrings(str1, str2) == "AB");
assert(gcdOfStringsWithMath(str1, str2) == "AB");
str1 = "LEET";
str2 = "CODE";
assert(gcdOfStrings(str1, str2) == "");
assert(gcdOfStringsWithMath(str1, str2) == "");
str1 = "TAUXXTAUXXTAUXXTAUXXTAUXX";
str2 = "TAUXXTAUXXTAUXXTAUXXTAUXXTAUXXTAUXXTAUXXTAUXX";
assert(gcdOfStrings(str1, str2) == "TAUXX");
assert(gcdOfStringsWithMath(str1, str2) == "TAUXX");
return 0;
}```
Last updated