农夫约翰出门沿着马路散步。但是他现在发现自己可能迷路了! 沿路有一排共
N
N
N 个农场。
不幸的是农场并没有编号,这使得约翰难以分辨他在这条路上所处的位置。
然而,每个农场都沿路设有一个彩色的邮箱,所以约翰希望能够通过查看最近的几个邮箱的颜色来唯一确定他所在
的位置。
每个邮箱的颜色用
A
.
.
Z
A..Z
A..Z 之间的一个字母来指定,所以沿着道路的
N
N
N 个邮箱的序列可以用一个长为
N
N
N 的由字母
A
.
.
Z
A..Z
A..Z 组成的字符串来表示。
某些邮箱可能会有相同的颜色。约翰想要知道最小的
K
K
K 的值,使得他查看任意连续
K
K
K 个邮箱序列,他都可以唯一确定这一序列在道路上的位
置。
例如,假设沿路的邮箱序列为 ABCDABC. 。
约翰不能令
K
=
3
K=3
K=3,因为如果他看到了 ABC , 则沿路有两个这一连续颜色序列可能所在的位置。
最小可行的
K
K
K 的值为
K
=
4
K=4
K=4,因为如果他查看任意连续4 个邮箱,那么可得到的连续颜色序列可以唯一确定他
在道路上的位置。
输入格式
输入的第一行包含
N
N
N,第二行包含一个由
N
N
N个字符组成的字符串,每个字符均在
A
.
.
Z
A..Z
A..Z之内。
输出格式
输出一行,包含一个整数,为可以解决农夫约翰的问题的最小
K
K
K 值。
数据范围
1
≤
N
≤
100
1\leq N\leq100
1≤N≤100
输入样例:
7
ABCDABC
输出样例:
4
分析:
题意是找到一个最小的长度K,使得每个长度为K的子数组都不相同,这样才能唯一标识位置,阅读题目后发现,要找到最小的K值,可以枚举K,使得得到最佳结果,而在枚举过程中,又可以用二分查找来优化。那结果怎么样才正确呢,要求子数组都不相同,可以用哈希来维护。
下面是完整代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<unordered_set>//相当于一个hash表
using namespace std;
int n;
string str;
bool check(int mid){
unordered_set<string> hash;
for(int i = 0; i+mid - 1<n;i++){
string s = str.substr(i,mid);//从i开始,长度为mid
if(hash.count(s)) return false;//说明找到两个一样的子串,k不满足,返回
hash.insert(s);
}
return true;
}
int main(){
cin >> n >> str;
int l = 1,r = n;
while(l < r){
int mid = l + r >> 1;
if(check(mid)) r = mid;//因为要找一个最小的k,mid右边的肯定满足
//而mid左边的有可能满足,所以要更新r区间继续找
else l = mid + 1;
}
cout << l << endl;
return 0;
}