在最多 T 成本下,將 A 的最長子串更改為 B 的子串
在這個問題中,我們將找到 A 的最長子串,將其轉換為從相同索引開始的 B 的子串,成本小於 T。
我們將使用二分查詢演算法來找到滿足給定條件的子串的最大長度。然而,解決這個問題的樸素方法是找到滿足問題陳述中條件的所有子串,並取長度最大的子串。
問題陳述 - 我們給定長度為 N 的字串 A 和 B。此外,我們還給定一個總成本“T”。K 是將一個字元轉換為另一個字元的成本。
我們需要找到 A 字串的最長子串,以便我們可以使其與 B 字串中從相同索引開始的子串相同,並且將一個子串轉換為另一個子串的總成本不應超過 T。此外,列印此類子串的起始和結束索引。
示例
輸入
A = "wxyz", B = "wpqt"; K = 2, T = 5;
輸出
Starting index – 0, ending index - 2
解釋
我們可以將“wxy”轉換為“wpq”,成本為 4,小於 5。
輸入
A = "wxyz", B = "ewrt"; K = 6, T = 5;
輸出
‘Not possible.’
解釋
這裡,K 大於 T,並且沒有從相同索引開始的子串相同。因此,無法找到子串。
輸入
A = "pqdetr", B = "tqcets"; K = 1, T = 5;
輸出
Starting index – 0, ending index - 5
解釋
我們可以將字串 A 作為子串,因為它的 5 個字元不同,我們可以將其與字串 B 的成本為 5。
方法 1
在這種方法中,我們將使用二分查詢演算法來解決問題。我們將檢查是否存在長度等於“中間長度”的有效子串。如果是,我們將在 [中間長度,字串長度] 範圍內查詢有效子串長度。否則,我們將在 [0,中間長度] 範圍內查詢有效字串長度。
我們將使用滑動視窗技術來查詢特定長度的有效子串。
演算法
步驟 1 - 將 st_ind 和 end_ind 變數初始化為 -1,以儲存最長子串的起始和結束索引。
步驟 2 - 將“左”指標初始化為 0,將“右”指標初始化為字串長度 + 1。還將“maxLen”初始化為 0,以儲存子串的最大長度。
步驟 3 - 現在,我們需要使用二分查詢技術。因此,開始使用 while 迴圈進行迭代,直到左指標的值小於右指標的值。
步驟 4 - 透過將左和右的總和除以 2 來找到中間長度。
步驟 5 - 執行 isMidValid() 函式以檢查是否存在長度等於“中間長度”的子串。
步驟 5.1 - 在 isMidValid() 函式中,將“p”和“q”變數初始化為 0,作為滑動視窗指標。還將“ct”初始化為 0,以儲存當前視窗使其與 B 字串子串相同的成本。
步驟 5.2 - 將“isValid”變數初始化為 false,以跟蹤是否存在有效子串。
步驟 5.3 - 使用迴圈進行迭代,直到“q”小於 A 字串的長度。在迴圈中,如果 A[q] 和 B[q] 不相同,則將 K(將一個字元轉換為另一個字元的成本)新增到“ct”。
步驟 5.4 - 如果當前視窗的長度等於“midLen”,請按照以下步驟操作。
步驟 5.4.1 - 如果“ct”小於 T,則將“isValid”設定為 true,將“st_ind”更新為 p,將“end_ind”更新為 q。
步驟 5.4.2 - 要移動到下一個長度為“midLen”的視窗,請從“ct”中移除“A[p]”的成本,並將“p”的值增加 1。
步驟 5.5 - 將“q”的值增加 1。
步驟 5.6 - 返回“isValid”變數的值。
步驟 6 - 如果函式返回 true,則更新“maxLen”並在右半部分搜尋最大長度。否則,在左半部分搜尋最大長度。
步驟 7 - 最後,如果“st_ind”的值為 -1,則子串不可能。否則,列印最長有效子串的起始和結束索引。
示例
以下是上述演算法的程式 -
#include <stdio.h>
#include <string.h>
// Starting and ending position of valid substring
int st_ind = -1, end_ind = -1;
int isMidValid(int midLen, char A[], char B[], int K, int T) {
int p = 0, q = 0, len = strlen(A), ct = 0;
// To track whether any substring of length MidLen is valid
int isValid = 0;
while (q < len) {
// Cost for converting one character to another
ct += (A[q] != B[q]) ? K : 0;
// Shifting the window to the right
if (q - p + 1 == midLen) {
// For cost less than T
if (ct <= T) {
isValid = 1;
st_ind = p;
end_ind = q;
}
// Removing the left character from the window
ct -= (A[p] != B[p]) ? K : 0;
p++;
}
q++;
}
// Output
return isValid;
}
void printLongestSubstr(char A[], char B[], int K, int T) {
st_ind = -1, end_ind = -1;
// Left and right pointers for binary search
int left = 0;
int right = strlen(A) + 1;
// To store the maximum length
int maxLen = 0;
while (left < right) {
// Mid calculation
int midLen = (left + right) / 2;
// If midLen length is valid
if (isMidValid(midLen, A, B, K, T)) {
// Update max length
maxLen = midLen;
// Find the maximum length in the right half
left = midLen + 1;
} else {
// If mid is invalid, then find in the left half
right = midLen;
}
}
if (st_ind == -1)
printf("Not possible\n");
else
printf("Starting index - %d ending index - %d\n", st_ind, end_ind);
}
int main() {
char A[] = "wxyz";
char B[] = "wpqt";
int K = 2, T = 5;
printLongestSubstr(A, B, K, T);
return 0;
}
輸出
Starting index - 0 ending index - 2
#include <bits/stdc++.h>
using namespace std;
// Starting and ending position of valid substring
int st_ind = -1, end_ind = -1;
bool isMidValid(int midLen, string &A, string &B, int K, int T) {
int p = 0, q = 0, len = A.size(), ct = 0;
// To track whether any substring of length MidLen is valid
bool isValid = false;
while (q < len) {
// Cost for converting one character to other
ct += ((A[q] != B[q]) ? K : 0);
// Shifting the window to right
if (q - p + 1 == midLen) {
// For cost less than T
if (ct <= T) {
isValid = true;
st_ind = p;
end_ind = q;
}
// Removing left character from window
ct -= ((A[p] != B[p]) ? K : 0);
p++;
}
q++;
}
// output
return isValid;
}
void printLongestSubstr(string A, string B, int K, int T) {
st_ind = -1, end_ind = -1;
// Left and right pointers for binary search
int left = 0;
int right = A.size() + 1;
int len = A.size();
// To store the maximum length
int maxLen = 0;
while (left < right) {
// Mid calculation
int midLen = (left + right) / 2;
// If midLen length is valid
if (isMidValid(midLen, A, B, K, T)) {
// Update max length
maxLen = midLen;
// Find the maximum length in the right half
left = midLen + 1;
} else {
// If mid is invalid, then find in the left half
right = midLen;
}
}
if (st_ind == -1)
cout << "Not possible\n";
else
cout << "Starting index - " << st_ind << " ending index - " << end_ind << "\n";
}
int main() {
string A = "wxyz", B = "wpqt";
int K = 2, T = 5;
printLongestSubstr(A, B, K, T);
return 0;
}
輸出
Starting index - 0 ending index - 2
public class LongestValidSubstring {
// Starting and ending position of valid substring
static int st_ind = -1;
static int end_ind = -1;
public static boolean isMidValid(int midLen, String A, String B, int K, int T) {
int p = 0;
int q = 0;
int len = A.length();
int ct = 0;
// To track whether any substring of length MidLen is valid
boolean isValid = false;
while (q < len) {
// Cost for converting one character to other
ct += (A.charAt(q) != B.charAt(q)) ? K : 0;
// Shifting the window to the right
if (q - p + 1 == midLen) {
// For cost less than T
if (ct <= T) {
isValid = true;
st_ind = p;
end_ind = q;
}
// Removing the left character from the window
ct -= (A.charAt(p) != B.charAt(p)) ? K : 0;
p++;
}
q++;
}
// Output
return isValid;
}
public static void printLongestSubstr(String A, String B, int K, int T) {
st_ind = -1;
end_ind = -1;
// Left and right pointers for binary search
int left = 0;
int right = A.length() + 1;
// To store the maximum length
int maxLen = 0;
while (left < right) {
// Mid calculation
int midLen = (left + right) / 2;
// If midLen length is valid
if (isMidValid(midLen, A, B, K, T)) {
// Update max length
maxLen = midLen;
// Find the maximum length in the right half
left = midLen + 1;
} else {
// If mid is invalid, then find in the left half
right = midLen;
}
}
if (st_ind == -1) {
System.out.println("Not possible");
} else {
System.out.println("Starting index - " + st_ind + " ending index - " + end_ind);
}
}
public static void main(String[] args) {
String A = "wxyz";
String B = "wpqt";
int K = 2;
int T = 5;
printLongestSubstr(A, B, K, T);
}
}
輸出
Starting index - 0 ending index - 2
# Starting and ending position of valid substring
st_ind = -1
end_ind = -1
def is_mid_valid(mid_len, A, B, K, T):
global st_ind, end_ind
p = 0
q = 0
len_A = len(A)
ct = 0
# To track whether any substring of length MidLen is valid
is_valid = False
while q < len_A:
# Cost for converting one character to another
ct += K if A[q] != B[q] else 0
# Shifting the window to the right
if q - p + 1 == mid_len:
# For cost less than T
if ct <= T:
is_valid = True
st_ind = p
end_ind = q
# Removing the left character from the window
ct -= K if A[p] != B[p] else 0
p += 1
q += 1
# Output
return is_valid
def print_longest_substr(A, B, K, T):
global st_ind, end_ind
st_ind = -1
end_ind = -1
# Left and right pointers for binary search
left = 0
right = len(A) + 1
# To store the maximum length
max_len = 0
while left < right:
# Mid calculation
mid_len = (left + right) // 2
# If mid_len length is valid
if is_mid_valid(mid_len, A, B, K, T):
# Update max length
max_len = mid_len
# Find the maximum length in the right half
left = mid_len + 1
else:
# If mid is invalid, then find in the left half
right = mid_len
if st_ind == -1:
print("Not possible")
else:
print(f"Starting index - {st_ind} ending index - {end_ind}")
A = "wxyz"
B = "wpqt"
K = 2
T = 5
print_longest_substr(A, B, K, T)
輸出
Starting index - 0 ending index - 2
時間複雜度 – O((logN)*N),其中 O(N) 用於滑動視窗,O(logN) 用於二分查詢。
空間複雜度 – O(1),因為我們不使用任何動態空間。
結論
我們使用了二分查詢和滑動視窗這兩種不同的演算法來解決單個問題。在許多情況下,我們需要使用多種演算法來解決問題。
資料結構
網路
關係型資料庫管理系統 (RDBMS)
作業系統
Java
iOS
HTML
CSS
Android
Python
C 語言程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP