AT_arc097_a题解

AT_arc097_a题解

这题首先观察,发现字符串的长度很小,只有 \(5000\),所以暴力搜索子串,排序再去重就可以了。

STEP 1:子串

大家都知道函数substr,可以用来截取子串。那么根据下面大佬题解@zhaozeyu123 的说法:

一个长度大于 k 的字串的字典序肯定不在前 k 位。

所以枚举子串每次枚举到 \(k\) 就可以了。

for(int i=0;i<l;i++){//每个位置都要枚举
        for(int j=1;j<=k;j++){//枚举到k
            zi[++p]=s.substr(i,j);//函数截取
        }
    }

STEP 2:排序

排序大家都会,运用STL里的sort

sort(zi+1,zi+p+1);

STEP 3:去重

这是这篇题解最想给大家讲的地方。去重大家基本上都会用STL的unique函数。即:

unique(zi+1,zi+p+1);//去重函数

今天我来给大家介绍一种手写的去重好方法(不是桶):

我们排序结束后,发现一个序列中,如果一个数有许多个,一定连在一起。那么,如果一个数不等于它后面那个数,说明它不是和它自己挨在一起,就说明出现了一个新数。于是有了一下代码:

for(int i=1;;i++){
	    if(zi[i]!=zi[i+1])q++;//如果不等于,数字个数累加
	    if(q==k){//如果等于k就输出
	        cout<<zi[i]<<endl;break;
	    }
	}

这种方法虽然在这里麻烦,但是有的时候更方便进行操作,时间复杂度也和STL的 \(O(n)\) 相等。

AC代码1:

#include<iostream>
#include<algorithm>
using namespace std;
string s,zi[5000050];
int k,p,q;
int main(){
    cin>>s>>k;
    int l=s.size();
    for(int i=0;i<l;i++){
        for(int j=1;j<=k;j++){
            zi[++p]=s.substr(i,j);
        }
    }
    sort(zi+1,zi+p+1);
	unique(zi+1,zi+p+1);
	cout<<zi[k]<<endl;
    return 0;
}

AC代码2:

#include<iostream>
#include<algorithm>
using namespace std;
string s,zi[5000050];
int k,p,q;
int main(){
    cin>>s>>k;
    int l=s.size();
    for(int i=0;i<l;i++){
        for(int j=1;j<=k;j++){
            zi[++p]=s.substr(i,j);
        }
    }
    sort(zi+1,zi+p+1);
	for(int i=1;;i++){
	    if(zi[i]!=zi[i+1])q++;
	    if(q==k){
	        cout<<zi[i]<<endl;break;
	    }
	}
    return 0;
}
posted @ 2022-12-26 14:41  Luminescent冷光  阅读(39)  评论(1编辑  收藏  举报