牛客练习赛70(A-重新排列 )
这道题做了一晚上都没过,之后看到了大佬的代码,受益良多O(∩_∩)O
题目描述
牛牛有个很喜欢的字符串”puleyaknoi“。 牛牛有T个很长很长的字符串,他很喜欢把字符串中的子串(连续的某段)打乱,并且按照自己的喜好重新排列。 如果牛牛能把一段重新排列出他喜欢的字符串,他就会把这个子串称作:喜欢的子串。 牛牛是个懒人,他不喜欢对太长的子串进行重排,那样他会觉着眼镜很累。 你能帮他求出对于每个字符串,最短的喜欢的子串的长度是多少吗? 如果没有,请输出-1。
输入描述:
第一行一个表示数据组数接下来行每行一个字符串(保证字符串只含小写字母)
输出描述:
共T行每行一个答案
示例1
输入
复制
2
sxpuleyaaknoip
konijiwa
2
sxpuleyaaknoip
konijiwa
输出
复制
11
-1
11
-1
说明
sxpuleyaaknoip中puleyaaknoi可以重排成puleyaknoia,其中包含有puleyaknoi。konijiwa不能重新排列出puleyaknoi,所以是-1
我的思路:其实就是先把那个单词puleyaknoi这个单词的所有字母先存结束,之后根据 l 和 i 的关系进行前面头缩减(这里有点像尺取,就是先确定尾部满足条件的字串,之后在前面进行剪枝,找出最优解),找出最小的子串。
这是AC代码:里面有一些注释可以帮到你理解这个代码
#include<iostream>
#include<cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
int t,len,num[30];
int a[]={
'p'-'a','u'-'a','l'-'a','e'-'a','y'-'a','a'-'a','k'-'a','n'-'a','o'-'a','i'-'a'};
string s;
int check(){
//检查是否全部找到,只要有一个没找到,就不满足条件,返回0for(int i=0;i<=9;i++){
if(num[a[i]]){
}else{
return 0;}}return 1;
}
int main(){
int t;scanf("%d",&t);while(t--){
cin>>s;memset(num,0,sizeof(num));int len=s.length();int l=0,ans=1e5+7;for(int i=0;i<len;i++){
//从整个单词中的头开始找num[s[i]-'a']++;//如果所有单词的字母都找全了,进入循化while(check()){
//找出最优解ans=min(ans,i-l+1);//进行头部缩减num[s[l]-'a']--;l++;//printf("%d-%c-%d\n",i,s[i],ans);}}if(ans<=len){
printf("%d\n",ans);}else{
printf("-1\n");}}
}