http://www.1point3acres.com/bbs/thread-145290-1-1.html
// Find the largest K such that A^K is a subsequence of B, where A, B are two strings. |A| << |B|.
// Power of a string:
// Let A = xyxz 鏉ユ簮涓€浜�.涓夊垎鍦拌鍧�.
// Then,
// A^1 = A = xyxz
// A^2 = xxyyxxzz
// A^3 = xxxyyyxxxzzz
. 1point 3acres 璁哄潧
// Example:-google 1point3acres
// A = xyxz
// B = xabyzxz
// B xaybyxzxxxzz
// A xxyyxxzz
一开始思路就是k从1一个个试,不行就返回。找subsequence用dp。但是面试官说复杂度太高,就想到用双指针遍历。然后问了时间复杂度。 写好后他还要improve.想到用二分查找k.因为最小是1,最大是B.length()/A.length();
subsequence是不需要连续的。如果x^(K+1)是y的subsequence,x^(K)一定是y的subsequence
// Find the largest K such that A^K is a subsequence of B, where A, B are two strings. |A| << |B|.
// Power of a string:
// Let A = xyxz 鏉ユ簮涓€浜�.涓夊垎鍦拌鍧�.
// Then,
// A^1 = A = xyxz
// A^2 = xxyyxxzz
// A^3 = xxxyyyxxxzzz
. 1point 3acres 璁哄潧
// Example:-google 1point3acres
// A = xyxz
// B = xabyzxz
// B xaybyxzxxxzz
// A xxyyxxzz
The key of the problem is to find out the largest possible k, that the A^k is the subsequence of B.
How to find out the maximum K. The easiest way is k = lenB / lenA. But that could result to a false larger K.
A better approach is to calculate the frequency of each character in A and B. Then calculate the MIN(B[i] / A[i]).
How to find out the maximum K. The easiest way is k = lenB / lenA. But that could result to a false larger K.
A better approach is to calculate the frequency of each character in A and B. Then calculate the MIN(B[i] / A[i]).
public
int
findK(String A, String B) {
int
len1 = A.length(), len2 = B.length();
if
(len1 > len2) {
return
0
;
}
if
(len1 <=
0
) {
return
0
;
}
// remove space weird characters, capital to lower case etc if needed
A = preprocess(A);
// find signature for each A and B and get the max possible value for k
int
[] sigA =
new
int
[
256
];
int
[] sigB =
new
int
[
256
];
for
(
int
i =
0
; i < len1; i++) {
sigA[A.charAt(i)]++;
}
for
(
int
i =
0
; i < len2; i++) {
sigB[B.charAt(i)]++;
}
int
kMax = Integer.MAX_VALUE;
for
(
int
i =
0
; i < len1; i++) {
if
(sigA[A.charAt(i)] !=
0
) {
kMax = Math.min(sigB[A.charAt(i)] / sigA[A.charAt(i)], kMax);
}
}
int
lo =
0
, hi = kMax;
int
ret =
0
;
while
(lo <= hi) {
int
med = lo + (hi - lo) /
2
;
if
(isSubSeq(expand(A, med), B)){
ret = med;
lo = med +
1
;
}
else
{
hi = med -
1
;
}
}
return
ret;
}
String expand(String A,
int
k){
StringBuilder sbuf =
new
StringBuilder();
for
(
int
i =
0
; i < A.length(); i++) {
char
c = A.charAt(i);
for
(
int
j =
0
; j < k; j++) {
sbuf.append(c);
}
}
return
sbuf.toString();
}
boolean
isSubSeq(String A, String B) {
int
len1 = A.length(), len2 = B.length();
int
a =
0
, b =
0
;
while
(a < len1 && b < len2){
if
(A.charAt(a) == B.charAt(b)){
a++;
b++;
}
else
{
b++;
}
}
return
a == len1;
}
String preprocess(String A){
return
A.toLowerCase();
}
- public int findK(String A, String B){
- int len1 = A.length(), len2 = B.length();
- if (len1 > len2) return 0;
- if (len1 <= 0) return 0;
- // remove space weird characters, capital to lower case etc if needed.
- A = preprocess(A);
- // find signature for each A and B and get the max possible value for k. 鐗涗汉浜戦泦,涓€浜╀笁鍒嗗湴
- int[] sigA = new int[256];
- int[] sigB = new int[256];. Waral 鍗氬鏈夋洿澶氭枃绔�,
- for (int i = 0; i < len1; i++) sigA[A.charAt(i)]++;
- for (int i = 0; i < len2; i++) sigB[B.charAt(i)]++;
- int kMax = Integer.MAX_VALUE;. 鐣欏鐢宠璁哄潧-涓€浜╀笁鍒嗗湴
- for (int i = 0; i < len1; i++){
- if (sigA[A.charAt(i)] != 0) kMax = Math.min(sigB[A.charAt(i)] / sigA[A.charAt(i)], kMax);
- }
- int lo = 0, hi = kMax;. 鍥磋鎴戜滑@1point 3 acres
- int ret = 0;
- while (lo <= hi){
- int med = lo + (hi - lo) / 2;
- if (isSubSeq(expand(A, med), B)){
- ret = med;
- lo = med + 1; 鏉ユ簮涓€浜�.涓夊垎鍦拌鍧�.
- } else {
- hi = med - 1;
- }
- }
- return ret;
- }
- String expand(String A, int k){
- StringBuilder sbuf = new StringBuilder();
- for (int i = 0; i < A.length(); i++){
- char c = A.charAt(i);
- for (int j = 0; j < k; j++) sbuf.append(c);
- }. more info on 1point3acres.com
- return sbuf.toString();
- }
- boolean isSubSeq(String A, String B){
- int len1 = A.length(), len2 = B.length();
- int a = 0, b = 0;
- while (a < len1 && b < len2){
- if (A.charAt(a) == B.charAt(b)){
- a++;
- b++;
- } else {
- b++;. 鐗涗汉浜戦泦,涓€浜╀笁鍒嗗湴
- }
- }
- return a == len1;. 鐗涗汉浜戦泦,涓€浜╀笁鍒嗗湴
- }
- String preprocess(String A){
- return A.toLowerCase();
- }
一开始思路就是k从1一个个试,不行就返回。找subsequence用dp。但是面试官说复杂度太高,就想到用双指针遍历。然后问了时间复杂度。 写好后他还要improve.想到用二分查找k.因为最小是1,最大是B.length()/A.length();
subsequence是不需要连续的。如果x^(K+1)是y的subsequence,x^(K)一定是y的subsequence
- public int findLargestK(String s1, String s2){.鏈枃鍘熷垱鑷�1point3acres璁哄潧
- if(s1.length() < 1 || s1.length() > s2.length())
- return -1;
- int k = 1;
- int left = 1, right = s2.length() / s1.length();
- int lastK = -1;
- while(left <= right){
- k = left + (right - left)/2;
- String akString = generateKth(s1, k);
- if(isSub(akString, s2)){
- lastK = k;
- left = k + 1;
- }else{. visit 1point3acres.com for more.
- right = k - 1;
- }
- }
- return lastK;
- }
- private String generateKth(String s, int k){
- StringBuilder temp = new StringBuilder();
- for(int i = 0; i < s.length(); i++){
- for(int j = 0; j < k; j++){. Waral 鍗氬鏈夋洿澶氭枃绔�,
- temp.append(s.charAt(i));
- }
- }
- return temp.toString();
- }. more info on 1point3acres.com
- private boolean isSub(String s1, String s2){
- int i = 0;
- int j = 0;
- while(i < s1.length() && j < s2.length()){
- if(s1.charAt(i) == s2.charAt(j)){. 1point 3acres 璁哄潧
- i++;
- }
- j++;-google 1point3acres
- }
- if(i == s1.length())
- return true;
- return false;
- }