按位比较

时间:2016-06-03 18:59:00

标签: c++ bit-manipulation bitwise-operators

#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 ++学习一些明智的操作,但我无法理解这里发生的事情。

3 个答案:

答案 0 :(得分:6)

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

找到所有字符串中存在的字符数。

这是代码的细分。

    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个字符串,并且对于每个字符串,你用一个数组

存储它由它组成的字符

例如,让我们说第一个字符串是&#34; stack&#34;。你遍历这里的人物

    for (char ch : s)
        c |= 1 << (ch - 'a');
对于每个字符串,

c初始化为0。

在这个例子&#34; stack&#34;中,让我们看看c

会发生什么
  

c = c | 1&lt;&lt; (&#39; s&#39; - &#39; a&#39;)=&gt; c = c | 1&lt;&lt; 18(c的第18位设为1)

     

c = c | 1&lt;&lt; (&#39; t&#39; - &#39; a&#39;)=&gt; c = c | 1&lt;&lt; 19(c的第19位设为1)

     

c = c | 1&lt;&lt; (&#39; a&#39; - &#39; a&#39;)=&gt; c = c | 1&lt;&lt; 0(c的第0位设置为1)

     

c = c | 1&lt;&lt; (&#39; c&#39; - &#39; a&#39;)=&gt; c = c | 1&lt;&lt; 2(c的第2位设为1)

     

c = c | 1&lt;&lt; (&#39; k&#39; - &#39; a&#39;)=&gt; c = c | 1&lt;&lt; 10(c的第10位设置为1)

     
    

注意1 <&lt;&lt; n表示1左移n位数。所以1&lt;&lt; 3是= 0001&lt;&lt; 3 =二进制1000 = 2 ^ 3 = 8(如果你不理解转移)

  

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

  

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

我们继续为所有字符串。最后,a将在所有字符串占用的位置设置1位..

例如,如果字符串2是&#34; aaaaa&#34;

  

计算c显示c只有第0位设置。

     

a&amp; = c;这除掉了0以外的所有1(即,它将2,10,18和19位设置为0,因为它们不会出现在&#34; aaaaa&#34;)

和字符串3是&#34; zzzzza&#34;,最后,只会设置第0位

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

答案 1 :(得分:2)

这里没有多少事情发生,并且一点一点地分解它会发现它的作用:

#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;
}

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

请注意,当我使用单词&#34;假设&#34;在这里,我的意思是可能会发生坏事

答案 2 :(得分:1)

我们先来看看

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。