对于字符串里面含或者不含某些字符的最小或者最大子串的一些总结

链接: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;
   }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值