有一种用B和D组成字符串的规则: S(1)=B S(2)=BBD S(3)=BBDBBDD … S(n)=S(n−1)+B+reverse(flip(S(n−1)) 其中,reverse(s)指将字符串翻转,比如reverse(BBD)=DBB,flip(s)指将字符串中的B替换为D,D替换为B,比如flip(BBD)=DDB。 求这个字符串的第L位(从1开始)到第R位,含有的B的个数是多少?
时间: 2023-05-30 09:03:00 浏览: 90
首先观察规律,发现每个字符串中B和D的数量总是相等的,而且从第2个字符开始,每个字符中B的数量都是前一个字符中B的数量加1。因此可以先计算出每个字符中B的数量,然后对于查询区间[L,R],可以先找到包含第L个字符的字符串,然后将[L,R]范围内的B数量累加起来。
具体实现时,可以使用递推的方法计算每个字符串中B的数量。设cnt[i][j]表示第i个字符中前j个字符中B的数量,那么有以下递推式:
cnt[i][j]=cnt[i−1][j−1]+cnt[i−1][j]
其中第一个分量表示第i个字符中第j个字符是B的情况,第二个分量表示第j个字符是D的情况。边界情况是cnt[1][1]=1。
接下来,对于查询区间[L,R],可以先找到包含第L个字符的字符串S(k),然后将[L,R]范围内的B数量累加起来。具体地,设len[k]表示第k个字符串的长度,那么有以下几种情况:
1. L=1且R=len[k],直接返回cnt[k]。
2. L=1且R<len[k],返回cnt[k][R]。
3. L>1且R=len[k],返回cnt[k][len[k]]−cnt[k][L−1]。
4. L>1且R<len[k],返回cnt[k][R]−cnt[k][L−1]+2×(L−1)。
第一种情况比较简单,直接返回cnt[k]即可。对于其他情况,需要注意的是,当查询区间不包含整个字符串时,需要将区间的左端点和右端点分别减去前面字符串的长度之和,因为每个字符串的长度都是前一个字符串的两倍。而当查询区间包含整个字符串时,需要将区间的右端点减去1,因为整个字符串中间的那个字符属于前一半的字符串,而不属于后一半的字符串。
时间复杂度
预处理cnt数组的时间复杂度是O(n^2),每次处理查询操作的时间复杂度是O(1),因此总时间复杂度是O(n^2+q)。其中n是字符串的长度,q是查询操作的数量。
空间复杂度
需要O(n^2)的空间存储cnt数组。
阅读全文