http://codeforces.com/contest/814/problem/C

【题意】

给定一个长度为n的字符串s,一共有q个查询,每个查询给出一个数字m和一个字符ch,你的操作是可以改变字符串中的某些字母,最多改变m个,问操作后只包含字符ch的连续子序列最长是多少?

【思路】

方法一:

于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式比较流行的叫法是“尺取法”。

有关尺取的练习:

http://blog.csdn.net/acmer_sly/article/details/59524223

http://acm.hdu.edu.cn/showproblem.php?pid=5328

尺取是线性的,所以总的时间复杂度是O(qn).

方法二:
dp,对每个字母预处理,时间复杂度是O(26n^2)。

【Accepted】

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cmath>
 4 #include <vector>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <queue>
 9 #include <deque>
10 #include <stack>
11 #include <string>
12 #include <bitset>
13 #include <ctime>
14 #include<algorithm>
15 #include<cstring>
16 using namespace std;
17 typedef long long ll;
18 const int maxn=1502;
19 int n,q,m;
20 char s[maxn];
21 char ch[5];
22 
23 
24 int solve(char c)
25 {
26     //双指针 
27     int l=0,r=0;
28     int ans=0;
29     int cnt=0;
30     while(l<n&&r<n)
31     {
32         //右端点不断往后扫,直到不能再向右 
33         while(r<n && (s[r]==c||cnt<m))
34         {
35             if(s[r]!=c)
36             {
37                 cnt++;
38             }
39             r++;
40         }
41         //记下当前l下的解 
42         ans=max(ans,r-l);
43         while(l<=r && s[l]==c)
44         {
45             l++;
46         }
47         //找到第一个使cnt-1的l,r才能继续向右更新 
48         l++;
49         cnt--;
50     }
51     return ans;
52 }
53 int main()
54 {
55     while(~scanf("%d",&n))
56     {
57         scanf("%s",s);
58         scanf("%d",&q);
59         for(int i=0;i<q;i++)
60         {
61             scanf("%d%s",&m,ch);
62             int ans=solve(ch[0]);
63             printf("%d\n",ans);
64         }
65     }
66     return 0;
67  } 
尺取

相关文章: