这道题做的。。。。真是坎坷
先把代码粘上来然后一点一点说把
总之AC了
#include<cstdio>
#include<queue>
#include<iostream>
#include<string>
using std::cout; using std::endl;
using std::priority_queue;
using std::string;
using std::vector;
int min, max, want; int have = 0;
int lastFreq, currentFreq;
FILE *fin, *fout;
struct node {
node *child[2];
int freq;
string word;
node() {
child[0] = 0, child[1] = 0, freq = 0;
}
};
struct cmp {
bool operator()(node *a, node *b) {
return a->freq < b->freq;
}
};
struct strcmp {
bool operator()(string &a, string &b) {
if (a.length() == b.length()) {
int i = 0;
while (a[i] == b[i])i++;
return a[i] > b[i];
}
return a.length() > b.length();
}
};
priority_queue<string, vector<string>, struct strcmp>pending;
priority_queue<node*, vector<node*>, cmp>aq;
class Tree {
node *root, *scout;
void traversal(node *target) {
if (target->child[0])traversal(target->child[0]);
if (target->child[1])traversal(target->child[1]);
if (target->freq)aq.push(target);
}
public:
Tree() {
root = new node;
}
void insert(string key) {
scout = root; int target;
for (int i = 0; i < key.length(); i++) {
target = key[i] - '0';
if (!scout->child[target])scout->child[target] = new node;
scout = scout->child[target];
}
scout->freq++;
scout->word = key;
}
void anal() {
if (root->child[0])traversal(root->child[0]);
if (root->child[1])traversal(root->child[1]);
}
}instance;
void print(bool end) {
int wordsInSingleLine = 0;
while (!pending.empty()) {
fprintf(fout, "%s ", pending.top().c_str());
wordsInSingleLine++; pending.pop();
if (wordsInSingleLine == 6 && !pending.empty())fprintf(fout, "\n"), wordsInSingleLine = 0;
}
have++;
if (have == want)
exit(0);
if (end)fprintf(fout, "\n%d\n", currentFreq);
lastFreq = currentFreq;
}
int main() {
fin = fopen("input7.txt", "r");
fout = fopen("output.txt", "w");
fscanf(fin, "%d%d%d", &min, &max, &want);
string seq; char temp[1000];
while (fscanf(fin, "%s", &temp) != EOF) {
seq += temp;
}
for (int i = 0; i < seq.length(); i++) {
for (int j = min; j <= max&&j + i <= seq.length(); j++) {
instance.insert(seq.substr(i, j));
}
}
instance.anal();
lastFreq = aq.top()->freq;
while (!aq.empty()) {
if (aq.top()->freq == lastFreq)pending.push(aq.top()->word), aq.pop();
else break;
int wordsInSingleLine = 0;
fprintf(fout, "%d\n", lastFreq);
while (!pending.empty()) {
fprintf(fout, "%s ", pending.top().c_str());
wordsInSingleLine++;
if (wordsInSingleLine == 6)fprintf(fout, "\n"), wordsInSingleLine = 0;
pending.pop();
}
wordsInSingleLine = 0;
while (!aq.empty()) {
if (have == want)
return 0;
currentFreq = aq.top()->freq;
if (currentFreq != lastFreq) {
print(1);
}
pending.push(aq.top()->word);
aq.pop();
if (aq.empty()) {
print(0);
return 0;
}
}
}
}
由于一看题,第一反应便是词频统计,所以我就又想起来了字典树= =(我觉得我沉迷字典树不能自拔了= =)
根据题目,一个字串只会包括0与1,所以一个节点只需要包括两个子节点指针。字典树其余操作皆与常规字典树相同。插入时将对应终结点频数+1。
麻烦的是输入
输入时,首先注意可能有多行。
while(cin>>buffer){seq+=buffer;}
然后把所有可能字串加入字典树。注意,题目要求在一定长度之内的字串。这也是很多人想不通的地方。仔细想—一定长度之内的字串
这里有个小东西可以用:
string string::substr(int start,int len);
这个函数可以返回一个字串,以当前字串为基础,返回其中从start开始向后len位的子字串。
例如:
string example="this is an example";
example[5]=='i';//true
example=example.substr(5,2);//此时example=="is"
利用这个工具,我们可以找出长字串中所有可能子字串
string seq; //while(cin>>buffer) seq+=buffer
for(int i=0;i<seq.length();i++){
for(int j=最短长度;j<=最长长度;j++)
字典树.insert(seq.substr(i,j));
}
由于要按频率顺序依次输出字串,我想到了优先队列。
遍历整棵树,将所有终结点以频率为键值置入优先队列
struct cmp {
bool operator()(node *a, node *b) {
return a->freq < b->freq;
}
};
priority_queue<node*, vector<node*>, cmp>aq;
//以上代码的意思是:按照cmp类型的规则对node指针排序。
void traversal(node *target) {
if (target->child[0])traversal(target->child[0]);
if (target->child[1])traversal(target->child[1]);
if (target->freq)aq.push(target);
}
然后就来到了万恶的输出。
输出需要注意几个地方:
1:同频率字串的输出顺序。同样可以用优先队列+重设排序规则的办法。
2:注意恰好有六个字串同频率的情况。
就这样。
注意:这道题中一共有两个地方需要排序:一处是按照词频对字串排序,还有一处是相同词频的字串所按照的输出顺序。当然也可以通过数组存储+algorithm库的sort(),但我觉得用优先队列的话逻辑结构更为清晰。
推荐来自supersnow0622的题解http://blog.csdn.net/supersnow0622/article/details/10179133
炒鸡巧妙地解决了0 00 000的识别问题与字串间比较问题