【集合和映射】USACO Bronze 2019 December - 我在哪Where Am I?
题目描述
农夫约翰在马路上散步,结果觉得自己可能迷路了!
在这条路上有 NNN 个农场(1≤N≤1001 \leq N \leq 1001≤N≤100),它们排成一行。
不幸的是,这些农场都没有门牌号,使得农夫约翰很难判断自己在路上的位置。
不过,每个农场都有一个彩色的邮箱,所以农夫约翰希望:如果他观察到自己附近邮箱的颜色,就能唯一确定自己所处的位置。
每个邮箱的颜色用一个范围在 A..ZA..ZA..Z 的字母表示,因此整条路的邮箱可以表示为一个长度为 NNN 的字符串。 其中可能会有多个邮箱颜色相同。
农夫约翰想知道:最小的整数 KKK 是多少,才能保证无论他观察到连续 KKK 个邮箱的颜色,都能唯一确定这段序列在路上的位置。
例如,若邮箱序列是 ABCDABC
:
- 当 K=3K = 3K=3 时,如果他看到
ABC
,则可能是开头的前三个邮箱,也可能是末尾的后三个邮箱,无法唯一确定。 - 当 K=4K = 4K=4 时,任意连续的 444 个邮箱颜色序列都是唯一的,因此可以唯一确定位置。
输入格式
第一行输入一个整数 NNN。
第二行输入一个长度为 NNN 的字符串,表示邮箱的颜色,每个字符在 A..ZA..ZA..Z 范围内。
输出格式
输出一个整数,表示最小的 KKK。
样例输入
7
ABCDABC
样例输出
4
提交链接
Where Am I?
思路分析
找到最小的 K,使得所有长度为 K 的子串都是 互不相同的。
📌 把输入的字符串看作一条颜色序列。
我们要找到最小的 K,使得所有长度为 K
的连续子串都不重复。
举例:
- 字符串
"ABCDABC"
- 长度为 3 的子串:
ABC, BCD, CDA, DAB, ABC
→ 有重复 ❌ - 长度为 4 的子串:
ABCD, BCDA, CDAB, DABC
→ 全部不同 ✅ - 因此答案是
K = 4
。
- 长度为 3 的子串:
🧠 核心:枚举子串长度 + 检查唯一性
- 枚举
K
(从 1 到 N)。 - 对于每个
K
,提取所有长度为K
的子串。 - 用
set
或map
判断是否有重复。- 如果有重复 → 说明这个
K
不够。 - 如果没有重复 → 说明这个
K
可行。
- 如果有重复 → 说明这个
- 第一个满足条件的
K
就是答案 🏆。
参考代码
#include <bits/stdc++.h>
using namespace std;int main()
{// freopen("whereami.in" , "r" , stdin);// freopen("whereami.out" , "w" , stdout);int n;cin >> n;string color;cin >> color;color = ' ' + color;for(int s = 1; s <= n; s++) //枚举看到的长度{map<string , int>m;bool check = true;for(int i = 1; i <= n - s + 1; i++) //每一个起始位置 对应一个字符串{string door = color.substr(i , s);if(m.count(door)){check = false;break;} m[door] = 1;}if(check == true){cout << s;return 0;}}return 0;
}