子数组异或和为0的最多划分

子数组异或和为0的最多划分

题目描述

给定一个整型数组arr,其中可能有正有负有零。你可以随意把整个数组切成若干个不相容的子数组,求异或和为0的子数组最多可能有多少个?整数异或和定义:把数组中所有的数异或起来得到的值。

输入描述:

输出包括两行,第一行一个整数,代表数组长度n ( 1 ≤ n ≤ 1 0 6 ) (1 \leq n \leq 10^6) (1n106)。第二行有n个整数,代表数组arr ( − 1 e 9 ≤ a r r i ≤ 1 e 9 ) \left(-1e9 \leq arr_i \leq 1e9 \right) (1e9arri1e9)

输出描述:

输出一个整数,表示数组切割最多的子数组的个数。

示例1
输入
10
3 2 1 9 0 7 0 2 1 3
输出
4
说明
最优划分:{3,2,1},{9},{0},{7},{0},{2,1,3} 其中{3,2,1},{0},{0},{2,1,3}的异或和为0
备注:

时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)


题解:

动态规划,设 f[i] 表示在 a[0…i] 上作分割,异或和为0的子数组数量。假设在 a[0…i] 上存在最优分割,并且最后一个分割数组一定包含 a[i] ,那么这个最优分割的最后一个子数组只可能有以下两种情况:

  • 最优分割的最后一个子数组,异或和不等于0,此时 f [ i ] = f [ i − 1 ] f[i] = f[i - 1] f[i]=f[i1]

  • 最优分割的最后一个子数组,异或和等于0,假设 a[k…i] 是最优分割的最后一个子数组,并且异或和等于0,那么 f [ i ] = f [ k − 1 ] + 1 f[i] = f[k - 1] + 1 f[i]=f[k1]+1,问题变成如何求 k ?

    因为在 arr[0…i] 的最优分割中,最后一个子数组异或和等于0,arr[k…i] 是最后一个子数组,且 arr[k…i] 的异或和等于0,那么 k 是离 i 最近且异或和为0的位置。那么怎么求 k 呢?我们可以利用前缀和思想,保存 arr[0…i] 的异或和,假设 arr[0…i] 的异或和为 cur ,若 xor[0…i] == xor[0…j] ,则xor[i+1…j] = 0,我们只需要找到上个 cur 出现在什么位置,即 k-1 的位置。这样的话,我们需要使用一个哈希表记录每个异或和最后一次出现的位置。

代码:
#include <cstdio>
#include <vector>
#include <unordered_map>

using namespace std;

int main( void ) {
    int n, val;
    scanf("%d", &n);
    unordered_map< int, int > _hash;
    _hash[0] = -1;
    vector<int> f(n);
    int ans = 0;
    int ret = 0;
    for ( int i = 0; i < n; ++i ) {
        scanf("%d", &val);
        ans ^= val;
        if ( _hash.find( ans ) != _hash.end() ) {
            int idx = _hash[ans];
            if ( idx != -1 ) f[i] = f[idx] + 1;
            else f[i] = 1;
        }
        _hash[ans] = i;
        if ( i ) f[i] = max( f[i], f[i - 1] );
        if ( f[i] > ret ) ret = f[i];
    }
    return 0 * printf("%d\n", ret);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值