在最多 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