对给定二进制字符串的任意两个子字符串进行最大按位或运算

data structurec++programming

在这个问题中,我们需要找出给定字符串中任意两个子字符串的最大或值。

第一种方法是找出给定二进制字符串的所有子字符串,对每个字符串取或值,并打印最大或值。

另一种方法是将原始字符串作为一个子字符串,并从最左边的零开始取另一个子字符串,以最大化或值。

问题描述- 我们给出了一个二进制字符串 alpha。我们需要找出给定二进制字符串中任意两个子字符串的"或"值之和的最大值。

示例

输入

alpha = "1000010"

输出

1100011

说明- 第一个子字符串为"1000010",另一个子字符串为"000010"。当我们对两者取或值时,我们得到"1100011"。

输入

alpha = "1111";

输出

1111

说明- 该字符串已经是最大值。因此,我们可以取原始字符串和任何其他子字符串来获得最大值。

输入

alpha = "1100";

输出

1111

解释- 我们可以取 1100 个子字符串和 11 个子字符串来获得最大值。

方法 1

在此方法中,我们将给定二进制字符串的所有子字符串存储在列表中。然后,我们将对每个子字符串进行"或"运算并跟踪最大值。此外,我们将创建一个函数来比较两个子字符串并进行"或"运算。

算法

步骤 1 - 使用空字符串初始化"maxOR"字符串变量,以存储任意两个字符串的"或"运算的最大值。此外,定义 subStr 列表来存储所有子字符串。

步骤 2 - 遍历给定的二进制字符串,使用 substr() 方法获取所有可能的子字符串,并将其推送到 subStr 列表。 substr() 方法将起始索引作为第一个参数,将子字符串长度作为第二个参数。

步骤 3 - 开始遍历子字符串列表。同时,使用嵌套循环遍历所有其他子字符串,对当前子字符串与其他子字符串进行"或"运算。

步骤 4 - 执行 takeOR() 函数对两个字符串进行"或"运算。

步骤 4.1 - 如果 temp1 字符串较小,则在 temp1 字符串后附加初始零。否则,在 temp2 字符串后附加初始零。

步骤 4.2 - 使用空字符串初始化"res"字符串,以存储结果"或"值。

步骤 4.3 - 遍历 temp1 和 temp2 两个字符串。如果当前索引处有任何字符串包含"1",则将"1"附加到"res"字符串。否则,将"0"附加到"res"字符串。

步骤 4.4 - 返回"res"字符串。

步骤 5 - 获取 OR 值后,通过执行 getmax() 函数检查 OR 值是否大于 maxOR 字符串的值。

步骤 5.1 - 如果 temp1 的大小大于 temp2,则返回 temp1。同样,如果 temp2 的大小大于 temp1,则返回 temp1。

步骤 5.2 - 开始遍历字符串。

步骤 5.3 - 如果 temp1 中第 p 个索引处的字符大于 temp1,则返回 temp1。类似地,如果 temp2 中第 p 个索引处的字符大于 temp2,则返回 temp2。

步骤 5.4 - 最后,返回"temp1"字符串。

步骤 6 - 将 getMax() 函数的返回值存储在"maxOR"变量中。

步骤 7 - 返回"maxOR"变量的值。

示例

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

string takeOR(string &temp1, string &temp2) {
   // 如果字符串长度不相等,则在较小字符串的开头添加 0
   if (temp1.size() < temp2.size()) {
      int diff = temp2.size() - temp1.size();
      for (int p = 0; p < diff; p++) {
         temp1 = '0' + temp1;
      }
   } else if (temp1.size() > temp2.size()) {
      int diff = temp1.size() - temp2.size();
      for (int p = 0; p < diff; p++) {
         temp2 = '0' + temp2;
      }
   }

   string res = "";
   // 对两个字符串进行"或"运算
   for (int p = 0; p < temp1.length(); p++) {
      if (temp1[p] == '1' || temp2[p] == '1') {
         res += '1';
      } else {
         res += '0';
      }
   }
   return res;
}

string getMax(string temp1, string temp2) {
   // 如果大小不相等,则返回大字符串
   if (temp1.size() > temp2.size()) {
      return temp1;
   } else if (temp1.size() < temp2.size()) {
      return temp2;
   }

   // 比较两个字符串并返回最大字符串
   for (int p = 0; p < temp1.size(); p++) {
      if (temp1[p] > temp2[p]) {
         return temp1;
      } else if (temp1[p] < temp2[p]) {
         return temp2;
      }
   }
   return temp1;
}

string maxORVal(string alpha) {
   string maxOR = "";
   vector<string> subStr;
   // 获取给定字符串的所有子字符串
   for (int p = 0; p < alpha.length(); p++) {
      for (int q = 1; q <= alpha.length() - p; q++) {
         subStr.push_back(alpha.substr(p, q));
      }
   }

   // 获取两个子字符串的最大或值
   for (int p = 0; p < subStr.size(); p++) {
      for (int q = p + 1; q < subStr.size(); q++) {
        // 对两个字符串进行或运算
        string OR_res = takeOR(subStr[p], subStr[q]);
        // 获取最大字符串
        maxOR = getMax(maxOR, OR_res);
      }
   }
   return maxOR;
}

int main() {
   string alpha = "1000010";
   cout << "The maximum OR value of any two substrings of the given string  is " << maxORVal(alpha);
   return 0;
}

输出

给定字符串的任意两个子字符串的最大或值为 1100011

时间复杂度 - O(N*N*N),其中 O(N*N) 表示遍历所有子字符串,O(N) 表示查找最大值并对两个字符串进行或运算。

空间复杂度 - O(N*N) 表示存储所有子字符串。

方法 2

在此方法中,我们将从最左边的 0 开始取子字符串,并将其与原始字符串进行或运算,这将始终得出最大值。

算法

步骤 1 - 使用空字符串初始化"temp1"和"temp2"字符串以存储临时字符串。

步骤 2 - 接下来,我们需要从原始字符串中删除前导零。开始遍历字符串,当找到第一个"1"时,从该索引处获取子字符串,并将其存储在"temp1"中。

步骤 3 - 如果 p 等于字符串长度,则返回"0",因为字符串全为零。

步骤 4 - 开始遍历字符串,并将当前字符附加到"temp2"字符串。如果当前字符为"0",则将索引值存储在"x"中并跳出循环,因为我们需要从最左边的零开始取子字符串。

步骤 5 - 如果 x 等于"temp1"字符串的长度,则返回 temp2 字符串,因为它包含所有 1。

步骤 6 - 再次遍历字符串,对原始字符串和从最左边的零开始的子字符串进行"或"运算。

步骤 7 - 如果 temp1[p] 或 temp1[x] 等于"1",则将"1"附加到 temp2。否则,将"0"附加到 temp2。

步骤 8 - 最后,返回"temp2"字符串。

示例

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

string maxORVal(string alpha) {
   int p, q, len = alpha.length();
   string temp1 = "", temp2 = "";
   // 从字符串中删除前导零
   for (p = 0; p < len; p++) {
     if (alpha[p] == '1') {
       // 获取从 p 到 len 的子字符串
       temp1 = alpha.substr(p, len);
       break;
     }
   }
   // 对于全包含零的字符串,答案是"0"。
   if (p == len) {
     return "0";
   }
   int x, temp1_len = temp1.size();
   // 获取从开始到第一个零的子字符串
   for (x = 0; x < temp1_len; x++) {
     if (temp1[x] == '0') {
       break;
     }
     temp2 += temp1[x];
   }
   // 如果字符串全为 1,则答案为"1"。
   if (x == temp1_len)
     return temp2;
   // 获取最大 OR 值
   for (p = 0; p < temp1_len and x < temp1_len; p++, x++) {
     if (temp1[p] == '1' or temp1[x] == '1')
       temp2 += '1';
     else
       temp2 += '0';
   }
   // Return the answer
   return temp2;
}
int main() {
   string alpha = "1000010";
   cout << "The maximum OR value of any two substrings of the given string  is " << maxORVal(alpha);
   return 0;
}

输出

给定字符串的任意两个子字符串的最大或值为 1100011

时间复杂度 - 遍历字符串一次,复杂度为 O(N)。

空间复杂度 - 存储子字符串,复杂度为 O(N)。

第二种方法是第一种方法的优化版本。在第二种方法中,我们将从最左边的零开始的子字符串作为另一个子字符串,因为无论何时将其与原始字符串进行"或"运算,它总是会得出最大值。


相关文章