原题
给一个字符串,统计“red”或“er”等类似子串的个数。这里的子串可以不连续。
ps.如果计算整个数组的red子串数量,对每个e统计左边的r和右边的d相乘,再相加即可。但是不能查询一个区间的数量。
答案可以用前缀和组合出来:
1.记录prer、pree、pred
2.遇到r时,与下标i-1的pree组成下标i的preer,其余同理
for(int i=1;i<=n;i++){
if(s[i]=='r'){
prer[i]+=1;
preer[i] += pree[i-1];
preder[i] += prede[i-1];
}else if(s[i]=='e'){
pree[i]+=1;
prere[i] += prer[i-1];
prede[i] += pred[i-1];
}else if(s[i]=='d'){
pred[i]+=1;
preed[i] += pree[i-1];
prered[i] += prere[i-1];
}
prer[i] += prer[i-1],pree[i] += pree[i-1],pred[i] += pred[i-1];
prere[i] += prere[i-1],preed[i] += preed[i-1],prede[i] += prede[i-1],preer[i] += preer[i-1];
preder[i] += preder[i-1],prered[i] += prered[i-1];
}
计算区间内的er、red数量:
1.观察preer的计算过程,preer[r]-preer[l-1]并不是e和r都在该区间内的er子串数量,而是r在该区间内,而e在[1,r]区间内的er子串数量,所以还要减去sume(1,l-1)*sumr(l,r),其余长度为2的子串同理。
2.观察prered的计算过程,同理,要求‘r’、‘e’、‘d’都在该区间内的red子串数量,就要减去[1,l-1]区间内的字符和[l,r]区间内的字符构成red的子串数量,即[1,l-1]区间的re子串数量和[l,r]区间内的d数量、[1,l-1]区间内的r数量和[l,r]区间内的ed子串数量
auto sumr = [&](int l,int r) -> ll{
return prer[r]-prer[l-1];
};
auto sume = [&](int l,int r) -> ll{
return pree[r]-pree[l-1];
};
auto sumd = [&](int l,int r) -> ll{
return pred[r]-pred[l-1];
};
auto sumre = [&](int l,int r) -> ll{
return prere[r]-prere[l-1] - sumr(1,l-1)*sume(l,r);
};
auto sumer = [&](int l,int r) -> ll{
return preer[r]-preer[l-1] - sume(1,l-1)*sumr(l,r);
};
auto sumed = [&](int l,int r) -> ll{
return preed[r]-preed[l-1] - sume(1,l-1)*sumd(l,r);
};
auto sumde = [&](int l,int r) -> ll{
return prede[r]-prede[l-1] - sumd(1,l-1)*sume(l,r);
};
auto sumred = [&](int l,int r) -> ll{
return prered[r]-prered[l-1] - sumre(1,l-1)*sumd(l,r) - sumr(1,l-1)*sumed(l,r);
};
auto sumder = [&](int l,int r) -> ll{
return preder[r]-preder[l-1] - sumde(1,l-1)*sumr(l,r) - sumd(1,l-1)*sumer(l,r);
};