USACO3.1.5 Contact 联系(枚举)
Description
奶牛们开始对用电波望远镜扫描牧场外的宇宙感兴趣。最近,他们注意到了一种非常奇怪的脉冲调制微波被从星系的中央发射出来。他们希望知道电波是否是被某些地外生命发射出来的,还是仅仅是普通的的星星的心跳。 帮助奶牛们用一个能够分析他们在文件中记下的记录的工具来找到真相。他们在寻找长度在A到B之间(含)在每天的数据文件中重复得最多的比特序列 (1 <= A <= B <= 12)。他们在找那些重复得最多的比特序列。一个输入限制告诉你应输出多少频率最多的序列。 符合的序列可能会重叠,并且至少重复一次的序列会被计数。
Input
第一行: 三个用空格分隔的整数: A, B, N; (1 <= N < 50) 第二行及以后: 一个最多200,000字符的序列,全是0或1; 每行有80个字符,除了可能的最后一行。
Output
输出N个频率最高的序列(按照频率由高到低的次序)。由短到长排列频率相同的这些序列,如果长短相同,按二进制大小排列。如果出现的序列个数小于N,输出存在的序列。 对于每个存在的频率,先输出单独包含该频率的一行,再输出以空格分隔的这些频率。每行六个(除非少于六个剩下)。
Sample Input
2 4 10
01010010010001000111101100001010011001111000010010011110010000000
Sample Output
23
00
15
01 10
12
100
11
11 000 001
10
010
8
0100
7
0010 1001
6
111 0000
5
011 110 1000
4
0001 0011 1100
题目让根据频率输出,规则说的很清晰。个人感觉这个题应该是用字典树+优先队列解决的,但是map+优先队列居然过了,居然过了!?只能说是数太水了,毕竟求一个字串长为1-50。字符串长2*1e5的串,怎么着map也应该炸了吧!?(虽然map炸了优先队列也要炸23333)
估计还是题目数据范围给的不合理,或者就是自己太菜算错了~
还是说一下自己的思路吧
AC思路
对于串str,我们从str[0]-str.size()-a
进行遍历,然后对于每一条子串,我们再找它的长为a-b
的串,并用hash记录该字串出现次数,最后遍历map,将元素扔进优先队列,前n个就是要求的结果
自己的思路
自己这个思路因为AC了就没再尝试了,不过这应该才是正解:
还是对str进行遍历,不同的是,每次传入的串长度为b,然后插入到字典树中去,这样最多只需要5021e5就能求出所有子串的出现次数,比map效率高(map插入操作所有子串插入为,这里的字典树每次长为b的字串插入(长为a-b的子串会在中途直接插入(),求子串所对应的二进制数也是中途),时间复杂度为).
放上第一种思路AC后的代码
#include <map>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <algorithm>
#define lowbit(a) (a&(-a))
#define _mid(a,b) ((a+b)/2)
#define _mem(a,b) memset(a,0,(b+3)<<2)
#define fori(a) for(int i=0;i<a;i++)
#define forj(a) for(int j=0;j<a;j++)
#define ifor(a) for(int i=1;i<=a;i++)
#define jfor(a) for(int j=1;j<=a;j++)
#define mem(a,b) memset(a,b,sizeof(a))
#define IN freopen("in.txt","r",stdin)
#define OUT freopen("out.txt","w",stdout)
#define IO do{\
ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);}while(0)
#define mp(a,b) make_pair(a,b)
#define debug(a) cout <<(a) << endl
using namespace std;
typedef long long ll;
const int maxn = 2*1e2+9;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f;
const double EPS = 1e-7;
const double Pi = acos(-1);
const int MOD = 1e9+7;
char str[2000005];
pair<string,int>PAIR;
struct cmp {
bool operator ()(pair<string,int>&a,pair<string,int>&b) {
if(a.second != b.second)
return a.second<b.second;
if(a.first.size() != b.first.size())
return a.first.size() > b.first.size();
return a.first > b.first;
}
};
string s;
map<string,int>qqq;
priority_queue<pair<string,int>,vector<pair<string,int> >,cmp>prique;
int main() {
//IN;
//OUT;
int x,b,n;
char c;
int cn = 0;
cin >> x >> b >>n;
while(~(c=getchar()))
if(c!='\n')
str[cn++] = c;
s = str;
for(int i=0; i+x<=s.size(); i++)
for(int j=x; j<=b&&j+i<=s.size(); j++)
qqq[s.substr(i,j)]++;
for(auto i:qqq)
prique.push(i);
int buf = -1;
int cnt = 0;
int cnr = 0;
bool flag = false;
while(!prique.empty()) {
if(buf!=prique.top().second){
if(cnr == n)
break;
buf = prique.top().second;
cout <<(flag?"\n":"")<<buf<<endl;
cnt = 0;
flag = true;
cnr++;
}
if(cnt==6)
cout << endl,cnt = 0;
if(cnt)
cout <<" ";
cnt++;
cout << prique.top().first;
prique.pop();
}
return 0;
}