当前位置: 代码迷 >> 综合 >> BestCoder #81 Div2 C String(尺取法)
  详细解决方案

BestCoder #81 Div2 C String(尺取法)

热度:60   发布时间:2023-12-08 10:57:44.0

题目链接:
BestCoder #81 Div2 C String
题意:
有一个10≤长度≤1,000,000 的字符串,仅由小写字母构成。求有多少个子串,包含有至少k(1≤k≤26)个不同的字母?
分析:
假设从s[0]到s[i]正好第一次满足出现K个不同的字母,那么从i开始到字符串尾都是满足的,一共是len-i个。0–i范围内的K个不同字母的子串还是可以缩短的,从0开始向后移动直到一个字母s[i]恰好出现一次,如果不包含s[j]一定只含有K-1个不同的字母,所以j是起始端的上限,一共是j-st+1个,所以这一次一共有(j-st+1)*(len-i)个不同的子串,更新st为j+1,i向后继续搜索。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
using namespace std;
const int MAX_N=(int)(1e6)+10;int T,K,vis[30];
char s[MAX_N];int main()
{freopen("81Cin.txt","r",stdin);scanf("%d",&T);while(T--){scanf("%s%d",s,&K);int len=strlen(s);int st=0,total=0;long long ans=0;memset(vis,0,sizeof(vis));for(int i=0;i<len;i++){if(vis[s[i]-'a']==0){vis[s[i]-'a']=1;total++;if(total==K){int j=st;for(j=st;vis[s[j]-'a']!=1;j++){vis[s[j]-'a']--;}//printf("st=%d j=%d i=%d\n",st,j,i);ans+=(j-st+1)*(len-i);st=j+1;total--;vis[s[j]-'a']=0;}}else {vis[s[i]-'a']++;}}printf("%lld\n",ans);}   return 0;
}
  相关解决方案