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;
}