小A很喜欢字母N,他认为连续的N串是他的幸运串。有一天小A看到了一个全部由大写字母组成的字符串,他被允许改变最多2个大写字母(也允许不改变或者只改变1个大写字母),使得字符串中所包含的最长的连续的N串的长度最长。你能帮助他吗?
小A很喜欢字母N,他认为连续的N串是他的幸运串。有一天小A看到了一个全部由大写字母组成的字符串,他被允许改变最多2个大写字母(也允许不改变或者只改变1个大写字母),使得字符串中所包含的最长的连续的N串的长度最长。你能帮助他吗?
输入的第一行是一个正整数T(0 < T <= 20),表示有T组测试数据。对于每一个测试数据包含一行大写字符串S(0 < |S| <= 50000,|S|表示字符串长度)。
数据范围:
20%的数据中,字符串长度不超过100;
70%的数据中,字符串长度不超过1000;
100%的数据中,字符串长度不超过50000。
对于每一组测试样例,输出一个整数,表示操作后包含的最长的连续N串的长度。
3 NNTN NNNNGGNNNN NGNNNNGNNNNNNNNSNNNN
4 10 18
#include<iostream> #include<string> using namespace std; int main() { int t; cin>>t; while(t--) { string s; cin>>s; int n=s.length(); int count=2; int k=0; int maxlen=0; for(int i=0;i<n;i++) { if(s[i]=='N') { k++; } else { if(count) { k++; count--; } else { count=2; i=i-k; k=0; } } if(maxlen<k) maxlen=k; } if(maxlen<k) maxlen=k; cout<<maxlen<<endl; } }
#include<iostream> #include<string> #include<algorithm> using namespace std; int main() { int t; cin>>t; for(int i=0;i<t;i++) { string s; cin>>s; int m=2; int r=0,sum=0; int add[2]={0}; for(auto &c:s) { if(c=='N') sum++; else if(m>0) { add[m-1]=sum; sum++; m--; } else { sum-=add[1]; add[1]=add[0]-add[1]-1; add[0]=sum-1; } r=max(r,sum); } cout<<r<<endl; } }
num_of_test = int(input()) for _ in range(num_of_test): string = input() window = [] res = 0 if len(string) - string.count('N') <= 2: print(len(string)) else: for i in string: window.append(i) while len(window) - window.count('N') > 2: window.pop(0) res = max(res, len(window)) print(res)参考楼上的(牛客864355626号)的答案。
number = input() for i in range(int(number)): a = input() b = [] c = 0 for j in a: b.append(j) if len(b) - b.count('N') >= 3: b.pop(0) c = max(c, len(b)) print(c)
动态规划,稍微优化了下,只保存前一个数据,以及最大的数据
#include <iostream> using namespace std; int main(){ int T; cin >> T; while(T > 0){ string s; cin >> s; int count = 0; // 保存修改一次和两次后N长度的最大值 int mTime1 = 0,mTime2 = 0; // 此时修改一次或两次后的长度 // 取代dp数组 int time1 = 0, time2 = 0; for(int i = 0; i < s.size(); i++){ if(s[i] == 'N'){ ++count; ++time1; ++time2; } else{ // 遇到的不是N,如果此时要修改且之前改了一次,那么time2和time1有关;如果此时要修改且之前为用修改次数,那么time1和count有关。 time2 = time1 + 1; time1 = count + 1; count = 0; } mTime1 = mTime1 > time1 ? mTime1 : time1; mTime2 = mTime2 > time2 ? mTime2 : time2; } cout << mTime2 << endl;; --T; } return 0; }
#include <iostream> using namespace std; int main(){ int n; cin>>n; while(n--){ string s; cin>>s; int cnt=0,_max=0; for(int i=-1,j=0;j<s.length();j++){ if(s[j]!='N') cnt++; while(cnt>2) if(s[++i]!='N') cnt--; _max=max(_max,j-i); } cout<<_max<<endl; } }
import java.util.Scanner; /** * @author lihaoyu * @date 2019/12/29 10:48 */ public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int T = scanner.nextInt(); for (int t = 0; t < T; t++) { String string = scanner.next(); int[] dp1 = new int[string.length() + 1]; int[] dp2 = new int[string.length() + 1]; int[] dp3 = new int[string.length() + 1]; for (int i = 0; i < string.length(); i++) { if (string.charAt(i) != 'N') { dp1[i + 1] = 0; dp2[i + 1] = dp1[i] + 1; dp3[i + 1] = dp2[i] + 1; } else { dp1[i + 1] = dp1[i] + 1; dp2[i + 1] = dp2[i] + 1; dp3[i + 1] = dp3[i] + 1; } } int max = 0; for (int i = 0; i < dp3.length; i++) { max = Math.max(max, dp3[i]); } System.out.println(max); } } }
#include <iostream> #include <vector> using namespace std; int main(){ int T; cin >> T; while(T--){ string s; cin >> s; int count = 0; int res = 0; int change = 2; int slow = 0; for(int i = 0;i < s.size();i++){ if(s[i] != 'N'){ // if(change){ change--; }else{ // change == 0 , s[i] != 'N' //窗口缩小 while (slow < i && s[slow] == 'N') slow++; slow++; } } count = i-slow+1; res = max(res,count); } cout << res << endl; } return 0; }
#include<iostream> using namespace std; int main(){ int T; cin>>T; while(T--){ string str; cin>>str; int i = 0; int count = 0; int num = str.size(); int localmax = 0; for(int j = 0; j < num; j++){ if(str[j] != 'N'){ count++; } while(count>2){ if(str[i] != 'N'){ count--; } i++; } if(j-i+1 > localmax){ localmax = j-i+1; } } cout<<localmax<<endl; } }
统计并保存字符串中非N字符出现的位置,根据非N字符的位置遍历判断最长结果,时间复杂度2n。 #include<stdio.h> #include<vector> #include<string> #include<algorithm> #include<iostream> using namespace std; int res(string s){ int length = s.size(); vector<int> temp; //记录非 N 字符的位置 for(int i = 0;i < length;++i){ if(s[i] != 'N') temp.emplace_back(i); } if(temp.size() <= 2) //最长N串是原字符串 return length; int n = temp.size(); int cnt = 0; cnt = max(temp[2],length - temp[n - 3] - 1); for(int j = 2;j < n - 1;++j){ cnt = max(cnt,temp[j + 1] - temp[j - 2] - 1); } return cnt; } int main(){ //按条件输入 int n; vector<string> stringN; cin>>n; string s; cin.get(); for(int i = 0;i < n;++i){ getline(cin,s); stringN.emplace_back(s); } for(int i = 0;i < n;++i){ cout<<res(stringN[i])<<endl; } return 0; }
#include <iostream> #include <vector> using namespace std; int nextN(vector<char> vc,int i){ for(int j = i+1;j < vc.size();j++){ if(vc.at(j) == 'N'){ return j; } } return -1; } int main(){ int round = 0; cin>>round; for(int r = 0;r < round;r++){ vector<char> vc; char tmp; if(r == 0){ tmp = getchar(); } while(cin>>noskipws>>tmp && tmp != '\n'){ vc.push_back(tmp); } if(vc.size() == 0){ cout<<0<<endl; break; } int lack = 0; int start = 0; int len = 0; int max = 0; for(int i = 0;i < vc.size();i++){ if(vc.at(i)=='N'){ len++; } else if(lack < 2){ len++; lack++; if(lack == 1){ start = i; } } else{ if(max < len){ max = len; } i = start; lack = 0; len = 0; } } if(max < len){ max = len; } cout<<max<<endl; } return 0; }
滑动窗口
#include <iostream> using namespace std; int main() { int t; cin >> t; while (t--) { string strIn; cin >> strIn; int l = 0, r = 0, size = strIn.size(), exc = 0, maxs = 0; while (r < size) { if (strIn[r] != 'N') { ++exc; while (exc > 2 && l < r) { if (strIn[l++] != 'N') --exc; } } if (r - l + 1 > maxs) { // printf("%d -> %d, exc: %d, sum: %d\n", l, r, exc, r - l + 1); maxs = r - l + 1; } ++r; } printf("%d\n", maxs); } }
不过上次在博客里还看到个更简单的解法
#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; for (int i = 0; i < T; i++) { string str; cin >> str; vector<int> res; int max = -1; for (int j = 0; j < str.size(); j++) { if (str[j] != 'N') res.push_back(j); } if (res.size() <= 2) cout << str.size() << endl; else { max = res[2]; for (int k = 3; k < res.size(); k++) { max = (res[k] - res[k - 3] - 1) > max ? res[k] - res[k - 3] - 1 : max; } max = str.size() - res[res.size() - 3] - 1 > max ? str.size() - res[res.size() - 3] - 1 : max; cout << max << endl; } } return 0; }
妙啊,直接跳过所有的N,加速了窗口的滑动,只不过占用了一点空间O(n)
滑动窗口啰,leetcode上有原题
#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; for (int i = 0; i < T; i++) { int N; cin >> N; int cnt[32] = {0}; int res = 0; for (int j = 0; j < N;j++) { int num; cin >> num; int c = 0; while (num) { if (num & 1) c++; num = num >> 1; } if (++cnt[c] == 1) { res++; } } cout << res << endl; } return 0; }
import re N = int(input()) for _ in range(N): s = input() s = (re.sub(r'[A-M]', 'O', s)) s = (re.sub(r'[P-Z]', 'O', s)) t = s.split("O") t = [len(i) for i in t] myans = 0 if len(t)<3: temp = sum(t)+len(t)-1 if temp>myans: myans=temp for i in range(len(t)-2): temp = t[i]+t[i+1]+t[i+2]+2 if temp>myans: myans=temp print(myans)
#include<bits/stdc++.h> using namespace std; int main() { int T; string strT; getline(cin,strT); T=stoi(strT); while(T--) { string line; getline(cin,line); int l=0,r=0; int cnt=0,res=0; while(r<line.size()) { if(line[r]!='N') cnt++; while(cnt>=3 && l<r) { res=max(res,r-l); cnt-=(line[l]!='N'); l++; } r++; } res=max(res,r-l); cout<<res<<endl; } return 0; }
不用pop的方法T = int(input()) for i in range(T): s = list(input()) su = 0 m = [] for i in range(len(s)): if s[i] == 'N': su += 1 else: m.append(i) if len(m) <= 2: print(len(s)) else: length=[] length.append(m[2]+1) for k in range(1,len(m)-2): length.append((m[k + 2] - m[k-1])) length.append(len(s)-m[len(m)-3]) print(max(length)-1)
import java.util.*; public class Main { public static void main(String[] args){ Scanner scan = new Scanner(System.in); int T = scan.nextInt(); while(T>0){ --T; String S = scan.next(); System.out.println(longest(S)); } } public static int longest(String S){ ArrayList<Integer> list = new ArrayList(); for(int i=0;i<S.length();i++) if(S.charAt(i)!='N') list.add(i+1); int max=0; if(list.size()<=2) return S.length(); else if(list.size()==3){ return max=Math.max(S.length()-list.get(0),list.get(2)-1); }else{ //非N字符>3的情况 for(int j=0;j<list.size();j++){ //上下界考虑 if(j==0) max=Math.max(max,list.get(j+2)-1); else if(j==list.size()-2)//list.size()-1和list.size()-2即最后两个非N数都被化成N return max=Math.max(max,S.length()-list.get(j-1)); else //一般情况 max=Math.max(max,list.get(j+2)-list.get(j-1)-1); } return max; } } }
//滑动窗口思想, 但是卡在90过不去了,最后的例子也不显示哪里出错了,求大佬指出 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; int main() { int n; while(cin >> n) { while(n--) { string s; cin >> s; int flag = 2,Max = 0,end = 1; vector<int> v(s.size()+1,0); //找到不为N的地方将它改为N,然后继续往后面找最长的N for(int start = 0; start < (int)s.size(); ++start) { //不为N且没被更改过 if(s[start] != 'N' && v[start] == 0) { --flag; v[start] = 1; if(flag < 0) flag = 0; } if(start >= end) { end += start - end + 1; } while(end < s.size()) { if(s[end] == 'N') ++end; //不为N且还能更改,标记更改位置 else if(s[end] != 'N' && flag > 0 && flag <= 2) { ++end; v[end] = 1; --flag; } else if(s[end] != 'N' && flag <= 0) break; } Max = max(Max,(end - start)); if(s[start] != 'N') { ++flag; } } cout << Max << endl; } } return 0; }
for i in range(int(input())): s1 = input() #dic1 = {} answer = [] if len(s1)<=2: print(len(s1)) else: for i in range(len(s1)): count = 0 num = s1[i] shuliang = 1 index = i if i == len(s1)-1: pass #print(s1[i+1:]) else: for j in s1[i+1:]: #print(j) if j != num and count <=2: count +=1 shuliang +=1 answer.append(shuliang) elif j == num and count <=2: shuliang+=1 answer.append(shuliang) elif index == (len(s1)-1): answer.append(shuliang) print(max(answer))我这个在本地是跑出来的,这里一直是报错,有没有大佬帮我看看哪里错了啊