问题描述
对于字符串 S
和 T
,只有在 S = T + ... + T
(T 与自身连接 1 次或多次)时,我们才认定 “T
能除尽 S
”。
返回最长字符串 X
,要求满足 X
能除尽 str1
且 X
能除尽 str2
。
示例
输入:str1 = "ABCABC", str2 = "ABC"
输出:"ABC"
输入:str1 = "ABABAB", str2 = "ABAB"
输出:"AB"
输入:str1 = "LEET", str2 = "CODE"
输出:""
- 1 <= str1.length <= 1000
- 1 <= str2.length <= 1000
- str1[i] 和 str2[i] 为大写英文字母
思路
这题我的思考过程是这样的:
如果str1和str2的长度相等,但是他俩值不等,肯定不行。为啥不行?因为他们都是x的数倍,即str1 = y1*x; str2 = y2*x;
他俩应该相等才对。不相等肯定不行(这也是我2B的原因)
如果str1
和str2
的长度不等,则x
的最大长度肯定是str1
和str2
长度的最大公约数。我们逐渐缩减x
的长度,来判定是否符合条件。(方法一)
方法一效率很低,只beat
了5%
。所以我要开始思考了:
我到底哪里出了问题?
先想想第一步,假设str1 = y1*x; str2 = y2*x;
那么,str1+str2 = (y1+y2)*x, str2+str1 = (y2+y1)*x;
那么str1+str2
如果 不等于 str2+str1
的话,那么就找不到这个x
。
再想第二步,我们第一步已经筛选出来了,保证是有解的。我们可以找出str1
长度和str2
长度的最大公约数。为啥求这个呢?因为str1
和str2
的长度都是最大公约数的数倍,同时内容上也是最大公约数长度的子串的数倍。(方法二)
方法二有个结论。懒得推导了,直接记住吧:
需要知道一个性质:如果 str1 和 str2 拼接后等于 str2和 str1 拼接起来的字符串(注意拼接顺序不同),那么一定存在符合条件的字符串 X。
方法一
Java版
public String gcdOfStrings1(String str1, String str2) {
if(str1.length() == str2.length() && str1.equals(str2)){
return str1;
}
int border = gcd(str1.length(),str2.length());
for(int i = border; i > 0; i--){
String pattern = str1.substring(0,i);
if(str1.split(pattern).length == 0 && str2.split(pattern).length == 0){
return pattern;
}
}
return "";
}
private int gcd(int m,int n) {
if(n == 0){
return m;
}
int r = m%n;
return gcd(n,r);
}
方法二
Java版
private int gcd(int m,int n) {
if(n == 0){
return m;
}
int r = m%n;
return gcd(n,r);
}
public String gcdOfStrings(String str1, String str2){
if(!(str1+str2).equals(str2+str1)){
return "";
}
return str1.substring(0,gcd(str1.length(),str2.length()));
}