按位比较
Bitwise comparisions
#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++ 中的位运算,但我无法理解这里发生了什么。
这里没有太多内容,一点一点地分解它会揭示它的作用:
#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 位可能不够。
请注意,当我在这里使用 "assume" 这个词时,我的意思是 可能会发生坏事 。
我们先来看看
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 中所有 c 中的那些位被设置为 1 while 块。
该代码不会确定特定字符是否存在于所有字符串中。
就是求所有字符串中出现的字符个数
这是代码的分解。
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 个字符串,对于每个字符串,你将其组成的字符存储在一个位数组中
例如,假设第一个字符串是“stack”。你在这里遍历字符
for (char ch : s)
c |= 1 << (ch - 'a');
c 为每个字符串初始化为 0。
在这个“堆栈”示例中,让我们看看 c
会发生什么
c = c | 1 << ('s'-'a') => c = c | 1 << 18 (18th bit of c is set to 1)
c = c | 1 << ('t'-'a') => c = c | 1 << 19 (19th bit of c is set to 1)
c = c | 1 << ('a'-'a') => c = c | 1 << 0 (0th bit of c is set to 1)
c = c | 1 << ('c'-'a') => c = c | 1 << 2 (2nd bit of c is set to 1)
c = c | 1 << ('k'-'a') => c = c | 1 << 10 (10th bit of c is set to 1)
note that 1 << n means that 1 is left shifted by n digits. so 1 << 3 is = 0001 << 3 = binary 1000 = 2^3 = 8 (In case you did not understand shifting)
现在c是一个整数,它的0,2,10,18,19位被设置为1。a在循环之前被初始化为全1。
a &= c; this gets rid of all 1's except 0,2,10,18 and 19.
我们对所有字符串继续此操作。最后,a 将在所有字符串中占用的位置设置 1 位..
例如,如果字符串二是“aaaaa”
computing c reveals that c has only its 0th bit set.
a &= c; this gets rid of all 1's except 0 (ie., it sets 2,10,18 and 19th bits to 0, since they don't occur in "aaaaa")
字符串 3 是 "zzzzza",最后只设置 a 的第 0 位
因此,所有这些字符串中出现的字符数为1
#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++ 中的位运算,但我无法理解这里发生了什么。
这里没有太多内容,一点一点地分解它会揭示它的作用:
#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 位可能不够。
请注意,当我在这里使用 "assume" 这个词时,我的意思是 可能会发生坏事 。
我们先来看看
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 中所有 c 中的那些位被设置为 1 while 块。
该代码不会确定特定字符是否存在于所有字符串中。
就是求所有字符串中出现的字符个数
这是代码的分解。
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 个字符串,对于每个字符串,你将其组成的字符存储在一个位数组中
例如,假设第一个字符串是“stack”。你在这里遍历字符
for (char ch : s)
c |= 1 << (ch - 'a');
c 为每个字符串初始化为 0。
在这个“堆栈”示例中,让我们看看 c
会发生什么c = c | 1 << ('s'-'a') => c = c | 1 << 18 (18th bit of c is set to 1)
c = c | 1 << ('t'-'a') => c = c | 1 << 19 (19th bit of c is set to 1)
c = c | 1 << ('a'-'a') => c = c | 1 << 0 (0th bit of c is set to 1)
c = c | 1 << ('c'-'a') => c = c | 1 << 2 (2nd bit of c is set to 1)
c = c | 1 << ('k'-'a') => c = c | 1 << 10 (10th bit of c is set to 1)
note that 1 << n means that 1 is left shifted by n digits. so 1 << 3 is = 0001 << 3 = binary 1000 = 2^3 = 8 (In case you did not understand shifting)
现在c是一个整数,它的0,2,10,18,19位被设置为1。a在循环之前被初始化为全1。
a &= c; this gets rid of all 1's except 0,2,10,18 and 19.
我们对所有字符串继续此操作。最后,a 将在所有字符串中占用的位置设置 1 位..
例如,如果字符串二是“aaaaa”
computing c reveals that c has only its 0th bit set.
a &= c; this gets rid of all 1's except 0 (ie., it sets 2,10,18 and 19th bits to 0, since they don't occur in "aaaaa")
字符串 3 是 "zzzzza",最后只设置 a 的第 0 位
因此,所有这些字符串中出现的字符数为1