汉明距离 --- 字符串处理+前缀和+找规律

21级大数据拔尖班练习赛【周次:4】 - Virtual Judge

汉明距离表示两个等长字符串在对应位置上不同字符的数目,举例来说 "0011" 和 "0110" 中汉明距离为 |0 - 0| + |0 - 1| + |1 - 1| + |1 - 0| = 0 + 1 + 0 + 1 = 2。我们以d(x, y)d(x,y)表示字符串xx和yy之间的汉明距离,现在给出两个仅包含01的字符串x,yx,y,同时定义s(A,B)s(A,B)代表字符串AA中所有长度为|B|的子串,请你求出xx和s(y,x)s(y,x)的汉明距离的总和,也就是∑d(x,s(y,x))∑d(x,s(y,x))。

 输入1

01

0011

输出1

2

输入2

01

00111

输出2

3

思路

我们先取到x和y的长度:首先考虑x(01)的第一位(0),它只与y(0011)的前三位比较,如果y为0对答案没有贡献,只有y为1才对答案贡献1;再考虑x的第二位(1),它从y的第一位开始比较,一直到最后一位,只用y为0时才对答案贡献1,y为1则不贡献答案

于是我们看到二十万的数据,肯定不能使用双指针遍历两次,这样会得到n方的时间复杂度会狠狠超时,则很容易想到使用前缀和求这一段区间内0和1的出现次数

#include <iostream>
#include <cstring>
#include <algorithm>
typedef long long LL;

using namespace std;

const int N = 400010;

LL a[N],s[N];
string x,y;

int main(){
    cin>>x>>y;
    
    LL lenx=x.size(), leny=y.size();
    
    for(LL i=0 ; i<leny ; i++) a[i]=y[i]-'0';  //将每个1、0字符转化为int类型整数
    
    LL sum=0;
    for(LL i=0 ; i<leny ; i++){
        s[i]=s[i-1]+a[i];  //预处理前缀和
    }
    LL re=0;
    //我们只需考虑每位数字对答案的贡献
    for(LL i=0 ; i<lenx ; i++){
        if(x[i] == '0') re+=s[leny-lenx+i]-s[i-1];
        else if(x[i] == '1') re+=leny-lenx+1-(s[leny-lenx+i]-s[i-1]);
    }
    cout<<re;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chuckle_7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值