bluecode-基因序列同源分组问题

问题描述

用不含重复字母的字符串表示一段基因序列。如果一段基因序列可以通过以下任一操作得到另一个基因序列,则认为这两段基因是同源的(或者说有血缘关系):

  1. 增加一个字母
  2. 删除一个字母
  3. 改变一个字母

给定若干个基因序列,求一共有多少种不同的血缘关系(即连通分量的数量)。

输入规范

  • 输入仅包含小写字母
  • 基因序列的总数量不超过 10,000

示例

示例 1

输入: ["a", "b", "ab", "cde"] 输出: 2

解释:

  • "a"、"b" 和 "ab" 互为同源(可通过增加或删除一个字母相互转换)
  • "cde" 与其他序列不同源
  • 因此共有 2 个血缘组

示例 2

输入: ["a", "ab", "abc", "ba"] 输出: 1

解释:

  • 所有序列都在同一个连通分量中(可以通过一系列操作相互转换)
  • 因此共有 1 个血缘组
cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>

using namespace std;

class UnionFind {
    private:
        unordered_map<string, string> parent;
    
    public:
        UnionFind(const vector<string>& sequences){
            for(const string& s : sequences){
                parent[s] = s;
            }
        }
        
        string find(const string& s){
            if(parent[s] != s){
                parent[s] = find(parent[s]);
            }
            
            return parent[s];
        }
        
        void unionSets(const string& s1, const string& s2){
                string root1 = find(s1);
                string root2 = find(s2);
                if(root1 != root2){
                    parent[root1] = root2;
                }
        }
        
        int countRoots(){
            unordered_set<string> roots;
            for(const auto& entry : parent){
                roots.insert(find(entry.first));
            }
            
            return roots.size();
        }
};

int numHomologyGroups(vector<string>& sequences){
    unordered_set<string> seqSet(sequences.begin(), sequences.end());
    UnionFind uf(sequences);
    
    for(const string& s : sequences){
        unordered_set<char> chars(s.begin(), s.end());
        
        // 增加一个字符
        for(char c = 'a'; c < 'z'; ++c){
            if(chars.find(c) == chars.end()){
                for(int i = 0; i <= s.size(); ++i){
                    string newS = s.substr(0, i) + c + s.substr(i);
                        if(seqSet.find(newS) != seqSet.end()){
                            uf.unionSets(s, newS);
                        }
                }
            }
        }
        
         // Delete operation 
        for (size_t i = 0; i < s.size();  ++i) {
            string newS = s.substr(0,  i) + s.substr(i  + 1);
            if (seqSet.find(newS)  != seqSet.end())  {
                uf.unionSets(s,  newS);
            }
        }
        
        // Change operation 
        for (size_t i = 0; i < s.size();  ++i) {
            char originalChar = s[i];
            for (char c = 'a'; c <= 'z'; ++c) {
                if (c != originalChar && chars.find(c)  == chars.end())  {
                    string newS = s.substr(0,  i) + c + s.substr(i  + 1);
                    if (seqSet.find(newS)  != seqSet.end())  {
                        uf.unionSets(s,  newS);
                    }
                }
            }
        }
    }
    
    return uf.countRoots(); 
}


int main(){
    vector<string> sequences1 = {"a", "b", "ab", "cde"};
    cout << numHomologyGroups(sequences1) << endl; // Output: 2 
    
    vector<string> sequences2 = {"a", "ab", "abc", "ac"};
    cout << numHomologyGroups(sequences2) << endl; // Output: 1 
    return 0;
}
相关推荐
IT猿手1 小时前
基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
神经网络·算法·matlab·人机交互·无人机·强化学习·无人机三维路径规划
万能程序员-传康Kk4 小时前
旅游推荐数据分析可视化系统算法
算法·数据分析·旅游
PXM的算法星球4 小时前
【并发编程基石】CAS无锁算法详解:原理、实现与应用场景
算法
ll7788114 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
烨然若神人~4 小时前
算法第十七天|654. 最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
算法
爱coding的橙子4 小时前
每日算法刷题Day2 5.10:leetcode数组1道题3种解法,用时40min
算法·leetcode
程序媛小盐5 小时前
贪心算法:最小生成树
算法·贪心算法·图论
Panesle5 小时前
分布式异步强化学习框架训练32B大模型:INTELLECT-2
人工智能·分布式·深度学习·算法·大模型
多多*6 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle
逐光沧海6 小时前
数据结构基础--蓝桥杯备考
数据结构·c++·算法·蓝桥杯