D 穿过哈气之门
思路:
统计包含所有 m 种元素的连续区间数量,核心思路是用滑动窗口双指针
1.窗口定义:用左右指针l和r维护一个连续区间[l, r),表示当前正在处理的窗口。
2.右指针扩展:右指针r不断右移,将元素加入窗口,直到窗口包含所有 m 种元素(此时窗口[l, r-1]是最小合法窗口)。
3.统计合法区间:一旦窗口合法,所有以l为左边界、右边界≥r-1的区间都合法(共n - r + 1个),累加到结果中。
4.左指针收缩:左指针l右移,将元素移出窗口,若某元素彻底消失计数为 0,则更新当前包含的元素种类数,重复步骤 2~3。
代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n,m;
cin>>n>>m;
vector<int> num(n);
vector<int> cnt(m+1);//当前窗口中每种元素的出现次数
for(auto &x:num)cin>>x;
int now=0,ans=0;//当前窗口元素种类数 合法区间总数
for(int l=0,r=0;l<n;++l){
while(r<n&&now<m){
if(cnt[num[r]]++==0) now++;//先判断后自加
++r;
}
if(now==m)ans+= n-r+1;//以当前l为左边界、右边界≥r-1的所有区间
if(--cnt[num[l]]==0)now--;
}
cout<<ans<< endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
//int T; cin >> T; while (T--)
solve();
}
H 分词器
从文本当前位置开始,优先匹配词表中最长的有效 token,若无匹配则按单个字符分割
思路:
哈希集合存储词表并记录最长 token 长度,从文本当前位置开始,按最长可能长度尝试匹配词表,找到则记录并后移对应长度,无匹配则取单个字符,最终输出所有分词结果,贪心策略实现最长匹配。
数据结构:
unordered_set 存储词表,方便后续查询count
vector 存储分词结果,push_back依次添加分词结果
substr(pos, length)方法,方便截取任意位置、任意长度的子串
unordered_set + maxtoken:maxtoken限制最大尝试长度, unordered_set快速验证子串是否有效,不会尝试长度超过maxtoken的子串。
pos+ len:pos标记当前位置,len控制尝试的子串长度,通过pos += len或pos += 1更新位置,线性遍历。
matched + res:matched判断是否匹配成功,决定是添加匹配的 token 还是单个字符到res,最终通过res输出完整结果
代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
unordered_set<string> Cin;
int maxtoken=0;
for (int i = 0; i < n; ++i) {
string t;
cin >> t;
Cin.insert(t);
maxtoken=max(maxtoken,(int)t.length());//更新token最长长度
}
string text;
cin >> text;//输入需要分离的文本
vector<string> res;//存储分词结果
int pos = 0;//当前处理文本位置
while (pos<text.length()) {
bool matched=false;//标记是否找到匹配的token
int ma= min(maxtoken,(int)text.length()-pos);//取词表最长token长度和剩余文本长度的较小值
for (int len = ma;len>=1;--len) {
string son= text.substr(pos,len);//检查该子串是否在词表中,son截取text字串
if (Cin.count(son)) {
res.push_back(son);
pos+=len;
matched=true;
break;
}
}
if (!matched) {//如果没有匹配
res.push_back(text.substr(pos, 1));//取单个字符
pos += 1;
}
}
for (int j = 0; j < res.size();++j) cout<< res[j] << " ";
cout<<endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
//int T; cin >> T; while (T--)
solve();
}