[USACO]3.1.5 Contact

这道题做的。。。。真是坎坷
先把代码粘上来然后一点一点说把
总之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的识别问题与字串间比较问题

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值