我们用每种字符代表一种宝石,A表示红宝石,B表示蓝宝石,C代表紫水晶,D代表翡翠,E代表钻石,F代表玉石,G代表玻璃等等,我们用一个全部为大写字母的字符序列表示项链的宝石序列,注意项链是首尾相接的。每行代表一种情况。
输出学者能够拿到的最多的宝石数量。每行一个
ABCYDYE ATTMBQECPD
1 3
#include<iostream> #include<string> #include<algorithm> #include<map> using namespace std; int main(){ string s; int i,j,num,len; while(cin>>s){ len=s.length(); s=s+s; i=0,j=0,num=0; int Min=len; map<char,int> book; while(true){ while(i<s.length()&&num<5){ if((s[i]=='A'||s[i]=='B'||s[i]=='C'||s[i]=='D'||s[i]=='E') &&book[s[i]]++==0) num++; i++; } if(num<5) break; Min=min(Min,i-j); if((s[j]=='A'||s[j]=='B'||s[j]=='C'||s[j]=='D'||s[j]=='E') &&--book[s[j]]==0) num--; j++; } printf("%d\n",len-Min); } }//尺取法,求包含ABCDE的最短字串
#include<iostream> #include<string> #include<vector> using namespace std; //判断str从start开始长度为length的子串中是否包括了ABCDE bool isPerfect(string str, int start, int length) { vector<bool> vec(5, false);//5个bool标记ABCDE是否找到 for(int i = 0; i < length; i++) { int index = str[start + i] - 'A'; if(index < 5) vec[index] = true; } return vec[0] && vec[1] && vec[2] && vec[3] && vec[4]; } int main() { string str; while(cin >> str) { bool find = false; int n = str.size(); if(n <= 5) { cout << 0 << endl; continue; } str = str + str;//省去环处理 for(int length = 5; length <= n; length++)//长度 { for(int i = 0; i < n; i++)//起点 { if(isPerfect(str, i, length)) { cout << n - length << endl; find = true; break; } } if(find) break; } } }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println(gem(sc.nextLine())); sc.close(); } public static int gem(String str) { char[] ca = str.toCharArray(); int len = str.length(); for (int x = 5; x < len; x++) { // x为截取宝石的个数 for (int y = 0; y < len; y++) {//y为x确定的情况下迭代的次数 StringBuilder temp = new StringBuilder(""); for (int z = y; z < y + x; z++) { temp.append(ca[z % len]); } String t = temp.toString(); if (t.contains("A") && t.contains("B") && t.contains("C") && t.contains("D") && t.contains("E")) { return len - x; } } } return 0; } }
O(n^2)的暴力 从第一个开始 找出ABCDE或者长度超过了给的长度为止 更新最大剩余珠宝量
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int ha[5], ans;
int main(){
string a;
while(cin>>a){
ans = 0;
int len = a.length();
for(int i = 0; i < len; i++){
if(a[i] < 'A' || a[i] > 'E') continue;
memset(ha, 0, sizeof(ha));
int cnt = 1, j = (i + 1) % len, num = 1;
ha[int(a[i])-65] = 1;
while(cnt <= len){
cnt++;
if(a[j] >= 'A' && a[j] <= 'E' && ha[int(a[j])-65] == 0) {
ha[int(a[j])-65] = 1;
num++;
if(num == 5) {ans = max(ans, len-cnt); break;}
}
j = (j + 1) % len;
}
}
printf("%d\n", ans);
}
}
#include<iostream> #include<string> using namespace std; int main() { string str; while (cin>>str) { int len = str.length(); for (int i = 0; i < len; i++) { str.push_back(str[i]); } int min =len; for (int i = 0; i <= len+5; i++) { int flag= 0x0000; int temp= 0; int j = i; while ((j <=len + 5 )&& (flag!= 0x1f)) { if (str[j] >= 'A'&&str[j] <= 'E') { flag|=1<<(str[j]-'A'); } j++; temp++; if (flag == 0x1f) break; } if (temp < min&& 0x1f ==flag) min = temp; } cout << len - min << endl; } }
来解释一下思路,
此题本质上是在一个字符串中找出包含ABCDE的最小长度的子字符串,学者最后能拿到的宝石的数目就是 字符串的长度减去最小字符串的长度。
那么为了找出最短的字符串,我们可以用枚举发来找出所有可能包含的字符串:
1.首先子字符串要至少包含ABCDE五个宝石,那么子字符串的可能长度区间就是 5 至 字符串的总长度
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
System.out.println(handle(sc.nextLine()));
}
}
public static int handle(String string){
//最大包含所有宝石的子字符串长度范围 5 - string.length
//子字符串的长度依次递增
char[] chars=string.toCharArray();
for(int i=5;i<=chars.length;i++){
//从字符串每一位为起点,开始依次截取对应范围长度的所有子字符串
for(int j=0;j<string.length();j++){
//保存每一个截取完的字符串
StringBuffer buf=new StringBuffer();
for(int k=j;k<j+i;k++){
//k 为截取的索引,注意数组越界
buf.append(chars[k%string.length()]);
}
//验证截取的字符串是否包含所有的宝石,一旦包含,
//此字符串为最小长度
String subString=buf.toString();
if(subString.contains("A")
&& subString.contains("B")
&& subString.contains("C")
&& subString.contains("D")
&& subString.contains("E")){
return chars.length-subString.length();
}
}
}
// 没有找到包含的子字符串
return 0;
}
}
用一个整数表示某字符串所包含的宝石种类,第0bit为1,表示存在红宝石;第1bit为1,表示存在蓝宝石……以此类推。当两个字符合并的时候,只需要将两个整数按位取或,就能表示合并后存在的宝石种类。
#include<bits/stdc++.h> using namespace std; char dict(char c){ switch(c){ case 'A': return 1; case 'B': return 0b10; case 'C': return 0b100; case 'D': return 0b1000; case 'E': return 0b10000; default: return 0; } } int diamonds(string s){ int n=s.size(); int dp[n][n];//从dp[i][j]表示从i开始,长为j+1的串包含多少种宝石 for(int i=0;i<n;i++){ dp[i][0]=dict(s[i]); } for(int j=1;j<n;j++){ for(int i=0;i<n;i++){ dp[i][j]=dp[i][j-1]|dp[(i+j)%n][0]; if(dp[i][j]>=0b11111){ return n-j-1; } } } return 0; } int main(){ string s; while(cin>>s){ cout<<diamonds(s)<<endl; } return 0; }
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNext()) { String s = sc.nextLine(); char[] arr = (s+s).toCharArray(); int[] indexArr = {-1,-1,-1,-1,-1}; int takeMax = 0; for(int i = 0;i < arr.length;i++) { if(arr[i] >='A' && arr[i]<='E') { indexArr[arr[i] - 'A'] = i; if(indexFull(indexArr)) { takeMax = Math.max(takeMax,s.length() - stay(indexArr)); } } } System.out.println(takeMax); } } private static int stay(int[] indexArr) { int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for(int i = 0; i < indexArr.length;i++) { max = Math.max(max,indexArr[i]); min = Math.min(min,indexArr[i]); } return max - min + 1; } private static boolean indexFull(int[] indexArr) { for(int i = 0;i < indexArr.length;i++) { if(indexArr[i] == -1) { return false; } } return true; } }
# include <stdio.h>
# include <string.h>
int main(){
char s[10000];
int n,len,loc,i,j;
while(scanf("%s",s)!=EOF){
n = len = strlen(s);//n为项链长度,len为满足条件的一截珠宝的长度
for(i=0;i<n;++i){
if(s[i]<'F'){//从所选5种珠宝开始
int c[5]={0};//用c统计五种珠宝遇到的次数
for(j=0;j<len;++j){
loc=(i+j)%n;//使首尾相接
switch(s[loc]){
case 'A':c[0]++;break;
case 'B':c[1]++;break;
case 'C':c[2]++;break;
case 'D':c[3]++;break;
case 'E':c[4]++;break;
}
if(c[0]&&c[1]&&c[2]&&c[3]&&c[4])break;//5种珠宝同时出现,退出循环
}
if(j+1<len)len=j+1;
}
if(len==5)break;//若五种珠宝相连,则退出循环
}
printf("%d\n",n-len);
}
return 0;
}
import java.util.Scanner; public class FindSequence { public static void main(String[] argv) { Scanner sin = new Scanner(System.in); while(sin.hasNext()){ String s = sin.nextLine(); char[] c = s.toCharArray(); int length = c.length; int flag =0,max=0; int i,j,k; for(i=0;i<length;i++){ flag =0; for(j=i;j-i<length;j++){ if(c[j%length] == 'A'||c[j%length] == 'B'||c[j%length] == 'C' ||c[j%length] == 'D'||c[j%length] == 'E' ){ flag |= 1<< c[j%length]-'A'; if(flag == 31){ max =Math.max(max, length-j+i-1); break; } } } } System.out.printf("%d\n",max); } } }
#include <iostream> #include <cstring> #include <queue> using namespace std; int main() { int typeOfStone = 0, minlen = -1; int numOfStone[6] = {0}; string str; queue<int> que; cin >> str; str += str; for (int i = 0; i < str.size(); i++) { if (str[i] - 'A' < 5) { int p = str[i] - 'A'; if (numOfStone[p] == 0) typeOfStone++; numOfStone[p]++; que.push(i); if (typeOfStone >= 5) { while(numOfStone[str[que.front()] - 'A'] > 1) { numOfStone[str[que.front()] - 'A']--; que.pop(); } if (minlen == -1 || minlen > (i + 1 - que.front())) { minlen = i + 1 - que.front(); } } } } if (typeOfStone < 5) { cout << 0 << endl; } else { cout << (str.size()/2) - minlen << endl; } }
自己怎么测都没错 到这怎么就错了呢??? 望各位大佬指点 import java.util.*; public class Main { public static void main(String[] args) { String str = "ABCDE"; char[] ch = str.toCharArray(); Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String s = sc.next(); int len = 0; int maxSize = 0; //判断字符串中是否全部包含ABCDE 不包含直接输出0 if (haveABCDE(s, str) == false) { System.out.println(maxSize); } else { //处理字符串 OPABCDEF 变成 OPABCDEFOPA 方便计算最多拿到宝石数量 (环) s = changeStr(s, ch); for (int i = 0; i < s.length(); i++) { //ifLike方法判断字符串哪一位 是ABCDE 中的 if (ifLike(s.charAt(i), ch) == false) { len++; } else { if (maxSize <= len) { maxSize = len; } len = 0; } } System.out.println(maxSize); } } } public static String changeStr(String s, char[] ch) { int c = 0; for (int i = 0; i < ch.length; i++) { if (ifLike(s.charAt(i), ch) == true) { c = i; break; } } s = s + s.substring(0, c + 1); return s; } public static boolean ifLike(char c, char[] ch) { for (int i = 0; i < ch.length; i++) { if (c == ch[i]) return true; } return false; } public static boolean haveABCDE(String s, String s1) { for (int i = 0; i < s1.length(); i++) { if (s.contains(s1.substring(i, i + 1)) == false) { return false; } } return true; } }
分享一个简单粗暴的思路和解答。 1.将每次输入的数组直接乘2拼接起来(NN=N+N),然后每次初始化的判断区间是输入数组的长度(N),之后每次左边收一格(left+=1),发现不能收了之后开始收右边(right-=1) 2.两边都不能收的时候返回此时剩余的宝石(len(N)-(r-l)),存入数组,循环输入字符串长度的次数 3.打印存入每次循环的值中的最大值即可 import sys N=input() NN=N+N res=[] for i in range(0,len(N)): l=i;r=i+len(N)-1 left=0;right=0 while((left==0)|(right==0)): while(('A'in NN[l:r])&('B'in NN[l:r])&('C'in NN[l:r])&('D'in NN[l:r])&('E'in NN[l:r])): l+=1 left=1 l-=1 while(('A'in NN[l:r])&('B'in NN[l:r])&('C'in NN[l:r])&('D'in NN[l:r])&('E'in NN[l:r])): r-=1 right=1 r+=1 res+=[len(N)-(r-l)] print(max(res))
目标:找到最短的包含ABCDE的substring,总长度减去substring长度即为答案
思路:
1. 将字符串重复两次构成一个新字符串db
2. 左右两根指针,保持一个窗口
3. 每次移动左右指针后,检查l - r中间字符串是否包含ABCDE:
a. 如果不包含全部,r++
b. 如果全包含全部,l++,同时判断是否需要更新最小长度
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <limits.h>
using namespace std;
int main() {
string s;
while (cin >> s) {
string db = s + s;
int n = db.size();
int l = 0, r = 0, minLen = INT_MAX;
vector<int> check(5, 0);
if (db[0] >= 'A' && db[0] <= 'E') {
check[db[0] - 'A']++;
}
while (r < n) {
bool flag = true;
for (int num : check) {
if (num == 0) {
flag = false;
}
}
if (flag) {
minLen = min(minLen, r - l + 1);
int ind = db[l] - 'A';
if (ind >= 0 && ind <= 4) {
check[ind]--;
}
l++;
}
else {
r++;
if (r < n) {
int ind = db[r] - 'A';
if (ind >= 0 && ind <= 4) {
check[ind]++;
}
}
}
}
if (minLen == INT_MAX || minLen > int(s.size())) {
cout << 0 << endl;
}
else {
cout << int(s.si***Len << endl;
}
system("PAUSE");
}
}
/* 小学生代码233,让str=str+str就可以看成圈了,然后找出含ABCDE最短的 长度(len+1),然后用str的总长去减他再除二就是剩下的宝石数 */ #include <iostream> #include <string> #include <vector> #include <map> using namespace std; bool if_in_(char x, char wh[]) { for (int i = 0; i < 5; i++) { if (wh[i] == x) return true; } return false; } int is_finished(map<char, int> js) { if (js['A'] == 1 && js['B'] == 1 && js['C'] == 1 && js['E'] == 1 && js['D'] == 1) return 1; return 0; } int main() { char wh[] = { 'A', 'B', 'C', 'D', 'E'}; map<char, int> js; vector<int> len_sz; js['A'] = 0; js['B'] = 0; js['C'] = 0; js['D'] = 0; js['E'] = 0; string str; cin >> str; str += str; int num = 0; for (int i = 0; i < str.size(); i++) { if (if_in_(str[i], wh)) { for (int j = i; j < str.size(); j++) { if (if_in_(str[j], wh)) { js[str[j]] = 1; if (is_finished(js)) { len_sz.push_back(j - i); js['A'] = 0; js['B'] = 0; js['C'] = 0; js['D'] = 0; js['E'] = 0; break; } } } } } int len = str.size(); for (auto v : len_sz) { if (v < len) { len = v; } } cout << (str.size() - 2*(len+1)) / 2; return 0; }
#include <iostream> #include <string> #include <algorithm> #include <map> using namespace std; int main() { string s; while(cin>>s) { int l = s.length(); int left=0, right=0, cnt=0, Min=l; map<char, int> M; s = s + s; while(1) { while(right<s.length() && cnt<5) { if(s[right]>='A' && s[right]<='E' && M[s[right]]++==0) cnt++; right++; } if(cnt<5) break; Min = min(Min, right-left); if(s[left]>='A' && s[left]<='E' && --M[s[left]]==0) cnt--; left++; } cout<<l-Min<<endl; } return 0; }