链接:https://ac.nowcoder.com/acm/contest/9556/B
来源:牛客网
怕npy的牛牛
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
牛牛非常怕他的女朋友,怕到了走火入魔的程度,以至于每当他看到一个字符串同时含有n,p,y三个字母他都害怕的不行。现在有一个长度为m的只包含小写字母‘a’-‘z’的字符串x,牛牛想知道能令他不害怕的最长子串的长度是多少。(对于字符串”abc”来说,”c”,”ab”都是原串的子串,但”ac”不是原串子串)
示例1
输入
复制
“abcdefghijklmn”
返回值
复制
14
说明
因为所有子串都不同时含有n,p,y,所以最长子串的长度即为字符串x的长度14。
示例2
输入
复制
“ynp”
返回值
复制
2
说明
长度为2的字串”yn”,”np”都符合题意,不存在长度>=3的符合条件的子串。
示例3
输入
复制
“ypknnbpiyc”
返回值
复制
7
说明
“pknnbpi”为其符合条件的最长子串,长度为7。
备注:
对于40%40%的数据1\leq m\leq 1001≤m≤100
对于100%100%的数据1\leq m\leq 1, 000,0001≤m≤1000000
函数共有一个参数,即题目描述中的字符串x,保证字符串中字母均为小写字母
注意,所给字符串不含引号
对于这种题暴力枚举肯定是不可能通过的。老实说,对于字符串的操作基本上都是尺取法,这一题也不例外。
题目意思是不能同时含npy的最长子串。我们用一个vis数组存目前所有出现过的字符,然后直到其出现了npy我们的右指针开始移到,直到npy不同时出现为止。然后i-j+1就是当前区间的值了。
具体看代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回符合题意的最长的子串长度
* @param x string字符串
* @return int整型
*/
int vis[30];
bool check()
{
return vis['n'-'a']&&vis['p'-'a']&&vis['y'-'a'];//检查是不是含有npy
}
int Maximumlength(string x) {
// write code here
int len=0;
int r=x.length();
int j=0;
for(int i=0;i<r;i++)
{
vis[x[i]-'a']++;
while(check()&&j<i)//不满足(不能同时出现npy)
{
vis[x[j]-'a']--;
j++;
//向右移直到满足条件为止
}
len=max(len, i-j+1);
}
return len;
}
};
链接:https://ac.nowcoder.com/acm/contest/7509/A
来源:牛客网
重新排列
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
牛牛有个很喜欢的字符串”puleyaknoi“。
牛牛有T个很长很长的字符串,他很喜欢把字符串中的子串(连续的某段)打乱,并且按照自己的喜好重新排列。
如果牛牛能把一段重新排列出他喜欢的字符串,他就会把这个子串称作:喜欢的子串。
牛牛是个懒人,他不喜欢对太长的子串进行重排,那样他会觉着眼镜很累。
你能帮他求出对于每个字符串,最短的喜欢的子串的长度是多少吗?
如果没有,请输出-1。
输入描述:
第一行一个表示数据组数
接下来行每行一个字符串(保证字符串只含小写字母)
输出描述:
共T行每行一个答案
示例1
输入
复制
2
sxpuleyaaknoip
konijiwa
输出
复制
11
-1
说明
sxpuleyaaknoip中puleyaaknoi可以重排成puleyaknoia,其中包含有puleyaknoi。
konijiwa不能重新排列出puleyaknoi,所以是-1
备注:
T \leq 10T≤10,字符串长度不超过10^510
5
这一题跟上一题有点相反,这是包含puleyaknoi的最短子串。
一段字符串可以重新排列成喜欢的子串当且仅当“puleyaknoi”中每个字母在其中出现至少一次,当找到符合条件的右端点,更新答案,然后将左端点向右移动直到不符合要求,重复如上操作直至结束。
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
typedef long long ll;
vector<int>arr;
int vis[30];
bool check()
{
return vis['p'-'a']&&vis['u'-'a']&&vis['l'-'a']&&vis['e'-'a']&&vis['y'-'a']&&vis['a'-'a']&&vis['k'-'a']&&vis['n'-'a']&&vis['o'-'a']&&vis['i'-'a'];
}
int main()
{ int t;
cin>>t;
while(t--)
{ string s;
cin>>s;
int ans=1000000;
int r=0;
for(int l=0;l<s.length();l++)
{
//fill(vis,vis+30,0);
while(!check()&&r<s.length())//先找到一组满足条件的
{
vis[s[r]-'a']++;
r++;
}
if(check())
{
ans=min(ans,r-l);//更新答案
}
vis[s[l]-'a']--;//不断向右移
}
if(ans==1000000)
cout<<"-1"<<endl;
else
cout<<ans<<endl;
}
}