1169D 1900的题
但他就是思维题,还是有点暴力的思维题
题意:给你一个字符串,然后让你从其中选出一段[l,r],并且要这段中存在s[i]=s[i+j]=s[i+jx2], l<=i,i+jx2<=r。问你存在多少段这样的l,r。
思路:对于这个题目我一开始的想法就是找个等差的数列,然后进行划分。但是好像有点难实现,之后列出一些字符串,可以找到一个规律,当你划分的这一段长度大于等于9时,一定存在某个i和j使得这个段符合题条件。之后想到这个之后就可以尝试暴力了,毕竟9还是ok的。
虽然说是暴力,但还是有点思维在里面的。
首先是对l和j进行枚举,同时l+jx2的上限要小于上一个l对应的r,可一这样想,对l从大到小进行枚举,然后对当前l求出他能取最小的r,这里的r是指,正好l+jx2=r(对于当前l能符合条件的话),对于当前这个r他能得到的段数为len-r,即为[l,r],[l,r+1]…[l,len-1],(我的下标是从零开始)对于下一个l,即l-1,他r的上限小于上一个l对应的r,为什么这么说呢,因为你对于当前的l来说,你所能得到的段的数量为ans+=len-r,虽然有可能当你r大于上一个l对应的r但是没有这个必要了,因为你只需要上一个[l,r]的区间就行了,所以这里相当于一个减枝把。之后的代码实现就比较简单了,就几行而已。
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 3e5+10;
char str[maxn];
int main(){
scanf("%s", str);
ll ans = 0;
int len = strlen(str);
int tmp = len; //记录上一个l对应的r的值
for(int i = len-1; i >= 0; i--){
for(int j = 1; i+j*2 < tmp; j++){
if(str[i]==str[i+j]&&str[i]==str[i+j*2]){
tmp = i+j*2;break;
}
}
ans += len-tmp;
}
printf("%lld\n", ans);
return 0;
}