三元字符串中要替换的最少字符以删除 Q 查询的所有回文子字符串
给定一个长度为N的三元字符串S只包含'0' 、 '1'和'2'字符和Q查询包含一系列索引[L, R] ,每个查询[L, R]的任务是找到要转换为'0' 、 '1'或'2' 的最小字符数,这样在str[L]和str[R]之间不存在长度至少为 2 的回文子串。
例子:
Input: N = 10, Q = 3, S = “0200011011”, queries = {0, 4}, {1, 6}, {2, 8}
Output: 2 3 3
Explanation:
Query 1: {0, 4} ⇒ s = “02000” palindromic substrings present are “020”, “00”, “000”. Substring s can be changed to “02102” with 2 changes. “acbac” has zero palindromic substrings.
Query 2: {1, 6} ⇒ s = “200011” palindromic substrings present are “00”, “000”, “11”. Substring s can be changed to “201201″ with 3 changes. “cabcab” has zero palindromic substrings.
Query 3: {2, 8} ⇒ s = “aaabbab” palindromic substrings present are”00″, “000”, “0110”, “11”, “101”. Substring s can be changed to “1201201″ with 3 changes. “1201201” has zero palindromic substrings.
Input: N = 5, Q = 2, S = “bccab”, queries = {0, 4}, {1, 2}
Output: 2 1
朴素方法:给定问题可以通过递归修改给定查询的子字符串的每个字符并检查结果子字符串是否具有回文子字符串来解决。
时间复杂度: O(Q*3 N )
辅助空间: O(N)
有效的方法:给定的问题可以使用动态规划来解决,想法是使用以下观察预处理所有子字符串的可能答案:
- 如果 s i ≠ s i-1和 s i ≠ s i-2 ,则字符串有零个回文子串,即没有两个相邻字符相同,也没有两个替代字符相同,原因如下:
- 如果相邻字符相同,则形成偶数长度回文。
- 如果交替字符相同,则形成奇数长度回文。
- 如果字符串的第一个字符是“0”,那么下一个字符必须是“1”或“2”(因为 s i ≠ s i-1 )
- 如果第二个字符是 '1',那么第三个字符不能是 '0'(因为 s i ≠ s i-2 )或 '1'(因为 s i ≠ s i-1 )
- 因此第三个字符将是“2”。那么第四个字符只能是'1'。形成的字符串是“012012012..”
- 同样,在排列字符“0”、“1”和“2”并重复每个排列多次后,我们得到目标字符串“012012012…”、“120120120…”、“021021021…”等
- “0”、“1”和“2”字符有六种可能的排列,因此有六个目标字符串
现在,每个查询都可以通过将子字符串从L到R字符转换为六个目标字符串并检查其中哪些需要最少的操作来解决。这种方法每次查询都需要 O(N) 时间。该方法可以通过预处理给定的字符串进一步优化。以下是优化的解决方案:
- 令prefix[i]为包含将字符串转换为目标字符串i所需的最少操作数的数组。因此, prefix[i][j]是将字符串的前j个字符转换为目标字符串i所需的操作数。
- 在上述步骤的预处理之后,每个查询j可以在 O(1) 时间内使用每个可能的预处理字符串的公式作为currentCost和(prefix[i][r j ] – prefix[i][l j – 1])用于所有可能的序列并打印成本。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
#define SIZE 100005
using namespace std;
// Function to preprocess the cost of
// converting the first j character to
// each sequence prefix[i]
void preprocess(string& s, string& t,
int prefix[][SIZE],
int n, int i)
{
// Initialize DP array
prefix[i][0] = (s[0] != t[0]);
for (int j = 1; j < n; j++) {
// prefix[i][j] defines minimum
// operations to transform first j
// characters of s into sequence i
prefix[i][j]
= prefix[i][j - 1]
+ (s[j] != t[j % 3]);
}
return;
}
// Function to find the minimum number of
// changes required to make each substring
// between [L, R] non-palindromic
void minChangesNonPalindrome(
string str, int N, int Q,
vector > queries)
{
// Initialize the DP array
int prefix[6][SIZE];
// Initialize the 6 different patterns
// that can be formed to make substrings
// non palindromic
vector sequences
= { "012", "021", "102",
"120", "201", "210" };
for (int i = 0; i < 6; i++) {
// Preprocess the string with
// the ith sequence
preprocess(str, sequences[i],
prefix, N, i);
}
// Iterate through queries
for (int i = 0; i < Q; i++) {
int l = queries[i].first + 1,
r = queries[i].second + 1;
int cost = INT_MAX;
// Find the minimum operations by
// comparing 6 different patterns
// of the substrings
for (int j = 0; j < 6; j++) {
// Find the cost
cost
= min(
cost,
prefix[j][r]
- prefix[j][l]
+ (str[l] != sequences[j][l % 3]));
}
cout << cost << '\n';
}
}
// Driver Code
int main()
{
string S = "0200011011";
vector > queries
= { { 0, 4 }, { 1, 6 }, { 2, 8 } };
int N = S.length();
int Q = queries.size();
minChangesNonPalindrome(
S, N, Q, queries);
return 0;
}
Python3
# Python 3 program for the above approach
import sys
SIZE = 100005
# Function to preprocess the cost of
# converting the first j character to
# each sequence prefix[i]
def preprocess(s, t,
prefix,
n, i):
# Initialize DP array
prefix[i][0] = (s[0] != t[0])
for j in range(1, n):
# prefix[i][j] defines minimum
# operations to transform first j
# characters of s into sequence i
prefix[i][j] = prefix[i][j - 1] + (s[j] != t[j % 3])
return
# Function to find the minimum number of
# changes required to make each substring
# between [L, R] non-palindromic
def minChangesNonPalindrome(
st, N, Q,
queries):
# Initialize the DP array
prefix = [[0 for x in range(SIZE)]for y in range(6)]
# Initialize the 6 different patterns
# that can be formed to make substrings
# non palindromic
sequences = ["012", "021", "102",
"120", "201", "210"]
for i in range(6):
# Preprocess the string with
# the ith sequence
preprocess(st, sequences[i],
prefix, N, i)
# Iterate through queries
for i in range(Q):
l = queries[i][0] + 1
r = queries[i][1] + 1
cost = sys.maxsize-1
# Find the minimum operations by
# comparing 6 different patterns
# of the substrings
for j in range(6):
# Find the cost
cost = min(cost, prefix[j][r] - prefix[j][l]
+ (st[l] != sequences[j][l % 3]))
print(cost)
# Driver Code
if __name__ == "__main__":
S = "0200011011"
queries = [[0, 4], [1, 6], [2, 8]]
N = len(S)
Q = len(queries)
minChangesNonPalindrome(
S, N, Q, queries)
# This code is contributed by ukasp.
Javascript
2
3
3
时间复杂度: O(N + Q)
辅助空间: O(N)