HPU 5672 String【尺取法】【模拟】

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5672

【题意】给出一串字符(全是英文小写),找出含有k个不同字符的子串个数。

 

【思路】尺取法

 

AC代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 typedef long long ll;
 4 const int N=1e6+9;
 5 char s[N];//记录输入的数组 
 6 int k; 
 7 int vis[300];//标记所在区间每个字母出现的个数 
 8 int main()
 9 {
10     int T;scanf("%d", &T);//T组测试数据 
11     while(T--)
12     {
13         scanf("%s %d", s, &k);
14         int slen = strlen(s);
15         if(k == 1)
16         {
17             printf("%I64d\n", (ll)slen*(slen+1)/2);
18             continue;
19         }   
20         int head=0;
21         ll ans=0;//记录符合条件的区间的个数 
22         int cnt=0;
23         memset(vis,0,sizeof(vis));
24         for(int i=0;i<slen;i++)
25         {
26             if(vis[s[i]]>0)
27             {
28                 vis[s[i]]++;
29                 continue;
30             }
31             vis[s[i]]=1;
32             cnt++;
33             if(cnt==k)//次区间出现了k个不同的字母 
34             {
35                 while(head<i)//头指针小于尾指针 
36                 {
37                     ans += slen-i;//延长到尾部的满足条件的区间个数 
38                     if(vis[s[head]]==1)//区间的第一个字母只在区间只出现一次时 
39                     {
40                         vis[s[head]]=0;//区间首字母出现的个数置为 0 
41                         head++;//头指针后移一位 
42                         cnt--;//出现的不同字母的个数减一(目前来说 cnt = k-1) 
43                         break;
44                     }
45                     else
46                     {
47                         vis[s[head]]--;//首字母出现的次数减一 
48                         head++;//头指针后移一位 
49                     }
50                 }
51             }
52         }
53         printf("%I64d\n", ans);
54     }
55     return 0;
56 }
posted @ 2016-11-12 16:56  唐唐123  阅读(151)  评论(0编辑  收藏  举报