For two strings s
and t
, we say "t
divides s
" if and only if s = t + ... + t
(t
concatenated with itself 1 or more times)
Given two strings str1 and str2, return the largest string x
such that x
divides both str1
and str2
.
Example 1:
Input: str1 = "ABCABC", str2 = "ABC"
Output: "ABC"
Example 2:
Input: str1 = "ABABAB", str2 = "ABAB"
Output: "AB"
Example 3:
Input: str1 = "LEET", str2 = "CODE"
Output: ""
Example 4:
Input: str1 = "ABCDEF", str2 = "ABC"
Output: ""
Constraints:
1 <= str1.length <= 1000
1 <= str2.length <= 1000
str1
andstr2
consist of English uppercase letters.
這道題定義了一種兩個字符串s和t之間的整除關系,若s串可由若干個t串組成,則說t串可以整除s串。現在給了兩個字符串 str1 和 str2,現在讓找到一個最大的字符串x,使得其可以同時整除這兩個字符串。來分析一下,由於這個x會重復出現在字符串中,所以其一定是個前綴,則字符串的所有前綴都有可能是這個x,於是乎只要遍歷所有的前綴,然后來驗證其是否可以整除這兩個字符串就可以找到要求的x了。遍歷 str1 的所有前綴,若 str1 的長度不是這個前綴的長度的整數倍,或者 str2 的長度不是這個前綴長度的整數倍,直接跳過。否則直接分別復制前綴直到和 str1,str2 的長度相同,再比較,若完全一樣,則說明前綴是一個x,賦值給結果 res。這樣遍歷下來就能得到長度最長的x了,參見代碼如下:
解法一:
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
string res;
int m = str1.size(), n = str2.size();
for (int i = 0; i < m; ++i) {
if (m % (i + 1) != 0 || n % (i + 1) != 0) continue;
string pre = str1.substr(0, i + 1), target1, target2;
for (int j = 0; j < m / (i + 1); ++j) {
target1 += pre;
}
if (target1 != str1) continue;
for (int j = 0; j < n / (i + 1); ++j) {
target2 += pre;
}
if (target2 != str2) continue;
res = pre;
}
return res;
}
};
這道題用遞歸來做的話會變的異常的簡潔,我們仔細來觀察題目中給的例子,若存在這樣的x的話,那么短的字符串一定是長的字符串的子串,比如例子1和例子2。這樣的話其實是可以化簡的,當長串中的前綴(和短串的長度相同)不等於短串的時候,說明x不存在,可以直接返回空,否則從長串中取出和短串長度相同的前綴,繼續調用遞歸,直到其中一個為空的時候,返回另一個就可以了,參見代碼如下:
解法二:
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
if (str1.size() < str2.size()) return gcdOfStrings(str2, str1);
if (str2.empty()) return str1;
if (str1.substr(0, str2.size()) != str2) return "";
return gcdOfStrings(str1.substr(str2.size()), str2);
}
};
下面這種解法一行搞定碉堡了,由於 str1 和 str2 可以被同一個x串整除,那么 str1+str2 和 str2+str1 一定是相同的,不信大家可以自行帶例子去驗證。而且最大的x的長度是 str1 和 str2 長度的最大公約數相同(是不是感覺很神奇,求大佬證明),這樣的話直接濃縮到一行就搞定了,參見代碼如下:
解法三:
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
return (str1 + str2 == str2 + str1) ? str1.substr(0, gcd(str1.size(), str2.size())) : "";
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1071
參考資料:
https://leetcode.com/problems/greatest-common-divisor-of-strings/
https://leetcode.com/problems/greatest-common-divisor-of-strings/discuss/307242/C%2B%2B-3-lines