通过替换 Q 查询中的 K 个字符来检查子字符串是否为回文

data structurec++server side programmingprogramming

简介

在本教程中,我们实现了一种方法,通过替换 Q 查询中的 K 个字符来检查子字符串是否为回文。回文是从两个方向读都相同的单词。当您从正向或反向阅读回文单词时,它的发音相同。例如,madam,refer。

这里,Q 查询是一个数字数组,包含起始索引、结束索引和 K 的值。输入字符串的起始和结束索引值用于仅选择位于这些起始和结束索引值之间的那些字符(两个值都包括在内)。

对于该方法,考虑一个字符串 str,通过用 Q 查询替换其 K 个字符来检查其子字符串是否为回文。 K 是替换字符的数量,以使子字符串成为回文。

示例 1

String s = "abcdef"
Queries = {{1, 4, 2}, {0, 4, 2}}

输出

Yes
Yes

解释

上例中,字符串为"abcd"。

对于查询1 - [1, 4, 1],起始索引为1,结束索引为4,最多可替换2个字符。范围{1, 4}内的子字符串为"bcde"。

通过替换1个字符,可将其变为回文字符串,回文字符串为"bcdd"。

对于查询2 - [0, 4, 3],起始索引为0,结束索引为4,最多可替换2个字符,使子字符串变为回文。位于范围 {0, 4} 内的子字符串是"abcde"。

是的,它可以通过替换 2 个字符来成为回文字符串,并且该回文字符串是"abcba"。

示例 2

String s = "hello"
Queries = { { 1, 4, 0 }, {1, 4, 2 },  { 7, 10, 3 }};

输出

No
Yes
Yes

解释

输入字符串为"helloindia"

对于查询 - {1, 4, 0} - 起始索引为 1,结束索引为 4,最多可替换 0 个字符以使子字符串成为回文。位于范围 {1, 4} 内的子字符串为 ello。

不,它不能通过替换 0 个字符成为回文字符串。

对于查询 - {1, 4, 2} - 起始索引为 1,结束索引为 4,最多可替换 2 个字符以使子字符串成为回文。位于范围 {1, 4} 内的子字符串为"ello"。

是的,它可以通过替换 2 个字符成为回文字符串。替换 2 个字符后的回文字符串为 'elle'。

对于查询 - {7, 10, 3} - 起始索引为 7,结束索引为 10,最多可以替换 3 个字符以使子字符串成为回文。位于范围 {6, 9, 2} 内的子字符串为 'india'。

是的,它可以通过替换字符成为回文字符串。替换 2 个字符后的回文字符串为 'indni'。

语法

  • length() - 它是在 <string> 头文件中定义的字符串类库函数。它返回字符串的长度。字符串的长度就是字符串的字符数。

string_name.length();
  • vector − 它是 C++ 中用于存储元素的容器。它是一个动态数组,不受数组大小限制。它具有不同的数据类型。

vector<data_type> vector_name;
  • vector<vector<> − 它是 vector 中的 vector,一个二维 vector。其工作原理类似于普通 vector。每一行都是一个向量。

vector<vector<data_type> > vector_name;

算法

  • 初始化字符串 s。

  • 使用数字数组初始化查询。

  • 使用循环迭代字符串字符。

  • 创建一个 2d 向量,用于存储使用查询的起始和结束索引值生成的子字符串。

  • 使用子字符串处理查询并计算不匹配的字符。

  • 使用剩余字符转换一半不匹配的字符。

  • 如果更改的字符数等于或小于 k 的值,则输出为 Yes。

  • 如果替换的字符数大于 K 的值,则打印 No。

  • 处理所有查询。

示例 1

我们使用 C++ 中的动态规划实现了其中一个演示。动态规划降低了时间复杂度,并且不会多次执行相同的步骤。它将任务分成几部分并使用递归。

#include <bits/stdc++.h>
using namespace std;

//用户定义函数从生成的子字符串中找出回文字符串
void findPalindrome(string s, vector<vector<int> >& Q){
   int l = s.length();
   vector<vector<int> > dpa(26, vector<int>(l, 0));  // 二维数组存储字符数
   
   //迭代字符串以生成子字符串
   for (int x = 0; x < 26; x++)  {
      char currentCharVal= x + 'a';     // 当前字符的值
      for (int y = 0; y < l; y++) {
         // 使用计数器字符的新值更新 dp 数组
         if (y == 0)  {
            dpa[x][y] = (s[y] == currentCharVal); }
         else {
            dpa[x][y] = dpa[x][y - 1] + (s[y] == currentCharVal); 
         }
      }
   }
   
   // 处理查询
   for (auto query : Q) {
      int leftInd = query[0];
      int rightInd = query[1];
      int k = query[2];
      int unMatched = 0;      // 查找并存储不匹配的字符
      for (int x = 0; x < 26; x++){
         int cnt = dpa[x][rightInd] - dpa[x][leftInd] + (s[leftInd] == (x + 'a'));
         if (cnt & 1)
            unMatched++;  
      }
      int result = unMatched / 2; // 初始化结果变量的值
      
      // 定义输出条件
      if (result <= k) {cout << "YES\n"; }
      else {cout << "NO\n"; }
   }
}
int main() {
   string s = "helloindia";
   vector<vector<int> > Q;  // 初始化查询
   Q = { { 1, 4, 0 }, {1, 4, 2 }, { 6, 9, 2 }, { 3, 8, 4 }};
   
   // 调用函数来处理查询并生成子字符串
   findPalindrome(s, Q);
   return 0; 
}

输出

NO
YES
YES
YES

示例 2

我们可以不使用动态规划来实现本教程中的问题陈述。为了生成子字符串并处理查询,使用了循环。使用"changes"变量计算已更改的字符数。当更改数小于或等于 K 时,输出为 Yes,否则输出为 No。

使用 auto 自动定义变量的数据类型。

#include <iostream>
#include <vector>
using namespace std;

// 生成子字符串并处理查询以检查子字符串是否为回文的函数
void checkPalindrome(string s, vector<vector<int>>& Q)  {
   //处理查询
   for (auto query : Q)   {
      int leftVal = query[0];
      int rightVal = query[1];
      int k = query[2];
      int l = rightVal - leftVal + 1;
      int unmatchedCnt = 0;
      //用于存储字符值的向量
      vector<int> cnt(26, 0);
      //生成子字符串
      for (int x = leftVal; x <= rightVal; x++)
         cnt[s[x] - 'a']++;
      for (int x = 0; x < 26; x++)  {
         if (cnt[x] % 2 != 0)
            unmatchedCnt++; 
      }
      int changes = unmatchedCnt / 2;
      // 输出条件
      if (changes <= k) 
         cout << "YES\n";
      else{ 
         cout << "NO\n";  
      }
   }
}

//代码控制器
int main()  {
   string s = "helloindia";
   vector<vector<int>> Q = { { 1, 4, 0 }, {1, 4, 2 }, { 6, 9, 2 }, { 3, 8, 4 }};
   checkPalindrome(s, Q);
   return 0;
}

输出

NO
YES
YES
YES

结论

我们已经到了本教程的结尾。在本教程中,我们考虑一个字符串并通过查询生成子字符串。我们通过替换最多 K 个字符来检查子字符串是否可以是回文字符串。K 是将子字符串转换为回文字符串时替换的最大字符数。为了在 C++ 中实现该任务,我们使用了循环和动态规划。在本教程中,我们使用了一个二维向量来存储查询。


相关文章