HDOJ 5672//模拟
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5672
题意:有一个字符串S,字符串里面只包含小写字母,问有多少个子串里面有至少K个不同的字母;
思路:还是放在代码里面说会好一点,其实就是维护一个左端点和满足性质的最小右端点的过程。
1 #include <stdio.h> 2 #include <iostream> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <string.h> 6 #define N 1000100 7 char s[N]; 8 int vis[N]; 9 int t; 10 int k; 11 int main() 12 { 13 scanf("%d",&t); 14 while(t--) 15 { 16 scanf("%s",s); 17 scanf("%d",&k); 18 int len=strlen(s); 19 memset(vis,0,sizeof(vis));//标记字母出现的次数 20 long long int cnt=0,ans=0,len1=-1,sum=0; 21 for(int i=0;i<len;i++) 22 { 23 while(cnt!=k&&len1<len) 24 { 25 len1++; 26 if(len1>=len) 27 break; 28 if(vis[s[len1]-'a']==0) 29 cnt++;//每有一个不同的那么计数器就加一 30 vis[s[len1]-'a']++; 31 32 } 33 if(len1>=len)//枚举完了就跳出 34 break; 35 ans=ans+(len-len1);//如果(i,j)满足这个性质,那么(i,k)(K>=J)都满足这个性质 36 if(--vis[s[i]-'a']==0)//如果这个满足这个性质的子串里面这个字母只出现了一次,那么这个字母之后肯定是满足不了这个性质的,也就是不同的字母会少一个,就要重新再找一次满足性质的最小的右端点 37 cnt--; 38 } 39 printf("%lld\n",ans); 40 } 41 return 0; 42 }