[USACO12DEC]First!

本文详细解析了Luogu3065问题的解决方案,利用Trie树构建字符串前缀关系,通过拓扑排序判断字符串是否能成为最小字典序,最终筛选出符合条件的字符串集合。

Description

Luogu3065

Solution

首先,一个串要是最小的,别的串不能是它的前缀,且和它有相同前缀的串字典序都比他小。
Trie树是显然要用的,难点在于如何判断能否最小。其实这之中蕴含了字母间的大小关系,即同一层中,钦定的最小串的字符要比其它的大。然后就可以建一个有向图跑拓扑排序判环就行。

Code

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
#include <vector>

namespace wyx {

typedef int ll;

ll read() {
    ll ans = 0, fl = 1;
    char c;
    for (c = getchar(); c > '9' || c < '0'; c = getchar())
        if (c == '-') fl = -1;
    ans = c - '0';
    for (c = getchar(); c >= '0' && c <= '9'; c = getchar())
        ans = ans * 10 + c - '0';
    return fl * ans;
}

typedef double ld;
typedef unsigned long long ull;
const int N = 30010;

struct Trie {
    int to[N * 10][26], cnt, val[N * 10];
    Trie() {
        memset(to, 0, sizeof to);
        memset(val, 0, sizeof val);
        cnt = 0;
    }
    void add(const std::string& s) {
        int len = s.length();
        int now = 0;
        for (int i = 0; i < len; ++i) {
            if (!to[now][s[i] - 'a']) to[now][s[i] - 'a'] = ++cnt;
            now = to[now][s[i] - 'a'];
        }
        val[now]++;
    }
} Tr;
struct Graph {
    std::vector<int> g[26];
    int deg[26];
    void init() {
        for (int i = 0; i < 26; ++i) g[i].clear(), deg[i] = 0;
    }
    void adde(int x, int y) {
        g[x].push_back(y);
        deg[y]++;
    }
    bool toposort() {
        std::queue<int> q;
        for (int i = 0; i < 26; ++i)
            if (deg[i] == 0) q.push(i);
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i : g[x])
                if (--deg[i] == 0) q.push(i);
        }
        for (int i = 0; i < 26; ++i)
            if (deg[i]) return false;
        return true;
    }
} G;
std::string s[N];
int n, vis[N];

bool work(int x) {
    int now = 0, len = s[x].length();
    for (int i = 0; i < len; ++i) {
        if (Tr.val[now]) return false;
        for (int j = 0; j < 26; ++j) {
            if (j != s[x][i] - 'a' && Tr.to[now][j]) G.adde(s[x][i] - 'a', j);
        }
        now = Tr.to[now][s[x][i] - 'a'];
    }
    return true;
}

void main() {
    n = read();
    for (int i = 1; i <= n; ++i) std::cin >> s[i], Tr.add(s[i]);
    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
        G.init();
        if (work(i) && G.toposort()) {
            vis[i] = 1;
            cnt++;
        }
    }
    printf("%d\n", cnt);
    for (int i = 1; i <= n; ++i)
        if (vis[i]) {
            std::cout << s[i] << std::endl;
        }
}

};  // namespace wyx

int main() {
    wyx::main();
    return 0;
}

转载于:https://www.cnblogs.com/wyxwyx/p/usaco12decfirst.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值