密文搜索 | 第六届蓝桥杯国赛C++B组
福尔摩斯从 X 星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为 8 的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。
要考虑密码的所有排列可能性。
输入格式
第一行:一个字符串 s,全部由小写字母组成。
紧接着一行是一个整数 n,表示以下有 n 行密码。
紧接着是 n 行字符串,都是小写字母组成,长度都为 8。
输出格式
一个整数,表示每行密码的所有排列在 s 中匹配次数的总和。
数据范围
字符串 s 的长度不超过 220,
1≤n≤1000
输入样例:
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
输出样例:
4
样例解释
第一个密码匹配了 3 次,第二个密码匹配了 1 次,一共 4 次。
题解:
最早开始的思想是前缀和,用一个二维向量记录st中每一位之前的字母数量情况,再与那1000个密码进行比较,效率O(N2).
后面TLE了,于是换了移动窗口的思想,但是还是TLE了。
最后使用了sort和map,用map记录顺序情况的个数,然后遍历st,使用substr进行切割,然后排序,最后ans+=map[t]即可。时间O(N*Log2N)。
代码:
AC代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;
const int INF=1e16;
long long int ans=0;
map<string,int> mp;
void solve(){
int n;
string st;
cin >> st;
cin >> n;
for(int i=0;i<n;i++){
string s;
cin >> s;
sort(s.begin(),s.end());
mp[s]++;
}
for(int i=0;i<=st.size()-8;i++){
string a=st.substr(i,8);
sort(a.begin(),a.end());
ans+=mp[a];
}
cout << ans << "\n";
}
int main(){
solve();
}
TLE代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;
const int INF=1e16;
vector<vector<int>> pre((1<<20)+5,vector<int>(30,0));
vector<vector<int>> m(1001,vector<int>(30,0));
long long int ans=0;
void solve(){
int n;
string st;
cin >> st;
cin >> n;
for(int i=0;i<n;i++){
string s;
cin >> s;
for(int j=0;j<s.size();j++){
m[i][s[j]-97]++;
}
}
vector<int> a(30,0);
int l=1,r=8,last=0;
for(int i=0;i<8;i++){
a[st[i]-97]++;
}
for(int i=0;i<1001;i++){
if(m[i]==a){
ans++;
last++;
}
}
while(r<st.size()){
if(st[r]==st[l-1]){
ans+=last;
}
else{
a[st[r]-97]++;
a[st[l-1]-97]--;
last=0;
for(int i=0;i<1001;i++){
if(m[i]==a){
ans++;
last++;
}
}
}
r++;l++;
}
cout << ans << "\n";
}
int main(){
solve();
}