逐位比较

Bitwise comparisions

本文关键字:比较      更新时间:2023-10-16
#include <iostream>
using namespace std;
int main() {
int n, a = 0xfffffff;
cin >> n;
while (n--) {
string s;
cin >> s;
int c = 0;
for (char ch : s)
c |= 1 << (ch - 'a');
a &= c;
}
cout << __builtin_popcount(a) << endl;
return 0;
}

该代码用于查找一个字符是否至少出现在所有输入字符串中一次。有人能解释一下这个代码中发生了什么吗。我正在努力学习C++中的逐位运算,但我无法理解这里发生了什么。

代码不是用来确定是否在所有字符串中都存在特定字符。

它是查找所有字符串中存在的字符数。

这是代码的分解。

int n, a = 0xfffffff;
cin >> n;

n是用户的输入参数,用于确定字符串的数量。假设n是3

while (n--) {
string s;
cin >> s;
int c = 0;
for (char ch : s)
c |= 1 << (ch - 'a');
a &= c;
}

这是代码的主要部分。。

你得到n个字符串,每个字符串都存储它由哪些字符组成,在一个位数组中

例如,让我们说第一个字符串是"堆叠";。你循环浏览这里的字符

for (char ch : s)
c |= 1 << (ch - 'a');

对于每个字符串,c被初始化为0。

在这个例子中;堆叠";,让我们看看c 发生了什么

c=c|1<lt;('s-'a')=>c=c|1<lt;18(c的第18位设置为1)

c=c|1<lt;(不是'-'a')=>c=c|1<lt;19(c的第19位设置为1)

c=c|1<lt;('a'-'a')=>c=c|1<lt;0(c的第0位设置为1)

c=c|1<lt;('c'-'a')=>c=c|1<lt;2(c的第2位设置为1)

c=c|1<lt;('k'-'a')=>c=c|1<lt;10(c的第10位设置为1)

注意,1<lt;n表示1被左移了n位数字。所以1<lt;3是=0001<lt;3=二进制1000=2^3=8(如果您不了解换档)

现在c是一个整数,其0,2,10,18,19位设置为1。a在循环之前被初始化为所有的1。

a&=c这去掉了除0、2、10、18和19之外的所有1。

我们继续对所有字符串执行此操作。并且在最后,a将在所有串中占据的位置设置1位。。

例如,如果字符串2是";aaaaa";

计算c表明c只有它的第0位集。

a&=c这去掉了除0之外的所有1(即,它将2、10、18和19位设置为0,因为它们不出现在"aaaaa"中)

并且字符串3是"0";zzzzz a";,最后,只有a的第0位将被设置为

因此,所有这些字符串中出现的字符数为1

这里没有太多内容,一点一点地分解可以揭示它的作用:

#include <iostream>
using namespace std;
int main() {
// Initialize a bitmask, here assumed to be 32-bits
// which is probably "enough" for this case.
int n, a = 0xfffffff;
// Read in the number of strings to process
cin >> n;
// Assume n > 0
while (n--) {
string s;
// Read in a string
cin >> s;
int c = 0;
// For each character in this string
for (char ch : s)
// Turn on a bit on representing the character, where
// 'a' is bit 0, 'b' is 1, etc.
c |= 1 << (ch - 'a');
// Apply this mask to a
a &= c;
}
// Report on which bits are toggled
cout << __builtin_popcount(a) << endl;
return 0;
}

总的来说,这是一些非常草率的代码。任何非小写字母都可能导致未定义的行为。对于现代机器来说,大多数编译器都是64位的,因此仅设置32位可能不够。

请注意,当我在这里使用"假设"一词时,我的意思是坏事可能会发生

让我们先来看看

int c = 0;
for (char ch : s)
c |= 1 << (ch - 'a');

您可以使用变量c按位表示输入字符串的字符:

  • 如果字符串中出现字符a,则变量c中的位0设置为1
  • 如果字符串中出现字符b,则变量c中的第1位设置为1
  • 如果字符串中出现字符c,则变量c中的第2位设置为1
  • 等等

c中的所有其他位均为零。

完成一个字符串后,代码

a &= c;

被执行。此代码将变量a中的一个位设置为1,如果它之前是1,则c的相应位也是1。然后,函数继续读取下一个字符串,并再次执行相同操作。

在执行结束时,a的那些位恰好被设置为1,在while块中的所有c中都是1。