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 }