商品仓库
Problem
在仓库里有很多商品,你需要检索某一个商品出现的次数。
Input
第一行读入
然后一行一个整数
保证所有输入的字符串长度不超过
Output
对于每一个检索,输出有多少个商品的字符串包含查询的字符串(包含即为某一个子串)
Sample
Input 1
20
ad
ae
af
ag
ah
ai
aj
ak
al
ads
add
ade
adf
adg
adh
adi
adj
adk
adl
aes
5
b
a
d
ad
s
Output 1
0
20
11
11
2
Solution
对于这种检索字符串的题,容易想到把字符串都塞到字典树上。同时观察到每一个字符串长度很小,总状态数不会很大,这是可行的。
对于一个字符串的子串,可以将它视为一个后缀串的前缀。于是我们将每一个串的后缀串插入字典树,并且遍历每一位时都要累加,这样就插入好了每一个子串。
但直接统计答案会出问题,可能对同一个字符串统计到多次答案。所以每次累计数量的时候判一下这个子串是否在当前串中统计过了。
剩下的就是字典树常规操作了,不多言。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int kmax = 1e5 + 3;
const int kmaxM = 26;
int n, m;
string str;
int ch[kmax][kmaxM], ct = 1;
int s[kmax * kmaxM];
int l[kmax * kmaxM];
void Insert(int p, int t) { // Trie 树插入
int x = 1;
for (int i = p; i < str.size(); i++) {
int c = str[i] - 'a';
if (!ch[x][c])
ch[x][c] = ++ct;
x = ch[x][c];
s[x] += l[x] != t; // 若未在当前串出现过,则累加
l[x] = t;
}
}
int Calc() {
int x = 1;
for (int i = 0; i < str.size(); i++) {
int c = str[i] - 'a';
if (!ch[x][c])
return 0;
x = ch[x][c];
}
return s[x]; // 计算答案
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> str;
for (int p = 0; p < str.size(); p++) {
Insert(p, i);
}
}
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> str;
cout << Calc() << '\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】