• LeetCode 5799 最美字符串的数目


    题目:https://leetcode-cn.com/problems/number-of-wonderful-substrings/

    • 因为只关心字符出现的奇偶性 —> 可以用一个二进制位表示某个字母出现的奇偶性
    • 根据数据范围,字符串中只包含前10个字母 —> 用10个二进制位表示字符串中出现的的每个字母的奇偶性
    • 计算字符串中字母出现次数的前缀和 —> 只改变新增字符的奇偶性,可以用异或运算
    前缀和pre[i]定义为:s[0…i]中各个字母出现的奇偶性;
    pre[i] = pre[i - 1] ^ (1 << (s[i] - ‘a’));
    前缀和之差 pre[j] - pre[i - 1]表示:子串s[i…j] 中每个字母出现次数的奇偶性;(本题中用异或运算表示)
    (1 << (s[i] - ‘a’)) 表示新增字符的二进制位为1,其他位为0;
    该异或运算可以只改变单个二进制位的奇偶性。
    • 最美字符串:至多一个字母出现奇数次  —> 1)所有字符都出现偶数次;2)枚举出现奇数次的字符的二进制位
    如果下标不同位置的前缀和相等,则说明 前缀和i-1 以及 前缀和j 中各个字母出现的奇偶性是一样的。 
    即 pre[i - 1] = pre[j],
    则子串 s[i…j] 中每种字母都出现偶数次。 
    (intuition: 偶数 - 偶数 = 偶数, 奇数 - 奇数 = 奇数)
    所以如果前缀子串s[0…j]中某个字母出现的奇偶性和前缀子串s[0…i-1]中该字母出现的奇偶性一样,则该字母在子串s[i…j]中一定出现偶数次。
    1. 对于当前前缀和,找到与之相等的前缀和个数cnt1;
    2. 对于当前前缀和,枚举每个二进制位并将该二进制位取反(假设该二进制位表示的字母出现奇数次),找到与某个二进制位取反后的前缀和相等的前缀和个数cnt2;
    1.
    pre[i] = pre[i - 1] ^ (1 << (s[i - 1] - ‘a’));
    ans += cnt[pre[i]];
     
    2.
    for(int i = 1; i < 1024; i <<= 1) {
        ans += cnt[pre[i] ^ i];
    }
    代码:
     1 class Solution {
     2 public:
     3     long long wonderfulSubstrings(string word) {
     4         vector<long> cnt(1025, 0);
     5         cnt[0] = 1; // 空字符串
     6         int pre = 0;
     7         long ans = 0;
     8         for(char ch : word) {
     9             pre ^= (1 << (ch - 'a'));
    10             ans += cnt[pre];
    11             for(int i = 1; i < 1024; i <<= 1) {
    12                 ans += cnt[pre ^ i];
    13             }
    14             cnt[pre]++;
    15         }
    16         return ans;
    17     }
    18 };
  • 相关阅读:
    LVS三种模式配置及优点缺点比较
    LVS负载均衡-DR模式
    Nginx反向代理和负载均衡
    LNMP(centos7.6 Nginx1.16 MySQL5.7 PHP7 )
    Nginx常用模块
    表演中的晴天
    迷雾中前行
    mysql Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nona
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    ubuntu16 安装elasticsearch6.3问题
  • 原文地址:https://www.cnblogs.com/tristatl/p/14941199.html
Copyright © 2020-2023  润新知