c# - 打印具有最高分数的两个序列的所有比对

标签 c# algorithm data-structures dynamic-programming

Sequence Alignment是一个相当标准的问题,并在生物信息学领域的 DNA 或蛋白质比对中得到应用。我最近遇到了这个问题的不同版本。

给定两个输入字符串(假设字符串仅由 A、C、G、T 组成),问题基本上是根据以下矩阵找到最大对齐分数 --

   A  C  G  T  -
A  5 -1 -2 -1 -3  
C -1  5 -3 -2 -4
G -2 -3  5 -2 -2
T -1 -2 -2  5 -1
- -3 -4 -2 -1 Not Allowed

因此,如果 A 与 - 对齐,我们将 -3 添加到对齐分数,或者如果 G 与 T 对齐,我们将 -2 添加到分数,或者如果 C 与 C 对齐,我们添加 5。 因此,对于输入字符串 AGTGATG 和 GTTAG,最大对齐分数为 14,其中一个具有最大分数的对齐可以表示为

AGTGATG
-GTTA-G

对齐分数计算如下:A- = -3, GG = 5, TT = 5, GT= -2, AA = 5, T-= -1 和 GG = 5。将它们相加,-3 +5+5-2+5-1+5 = 14,这是这对字符串的最大可能对齐分数。

我能够使用动态编程对其进行编码并获得对齐分数矩阵,但我在打印具有最大对齐分数的两个字符串的所有可能对齐时遇到问题。我试着像在 LCS 中那样回溯,但没能成功。我附上了我的代码。

static Dictionary<string, int> dict;

    static void Main(string[] args)
    {
        //This has been assumed that the strings contain only A,C,G,T and -(?)..caps

        Console.WriteLine("Enter first string : ");
        string a = Console.ReadLine();
        a = "-" + a;
        Console.WriteLine("Enter second string : ");
        string b = Console.ReadLine();
        b = "-" + b;
        int[,] SQ = new int[a.Length, b.Length];
        #region Create Dictionary
        dict = new Dictionary<string, int>();
        dict.Add("AA", 5);
        dict.Add("AC", -1);
        dict.Add("AG", -2);
        dict.Add("AT", -1);
        dict.Add("A-", -3);

        dict.Add("CA", -1);
        dict.Add("CC", 5);
        dict.Add("CG", -3);
        dict.Add("CT", -2);
        dict.Add("C-", -4);

        dict.Add("GA", -2);
        dict.Add("GC", -3);
        dict.Add("GG", 5);
        dict.Add("GT", -2);
        dict.Add("G-", -2);

        dict.Add("TA", -1);
        dict.Add("TC", -2);
        dict.Add("TG", -2);
        dict.Add("TT", 5);
        dict.Add("T-", -1);

        dict.Add("-A", -3);
        dict.Add("-C", -4);
        dict.Add("-G", -2);
        dict.Add("-T", -1);
        dict.Add("--", 0);
        #endregion Create Dictionary

        for (int i = 0; i < a.Length; i++)
        {
            for (int j = 0; j < b.Length; j++)
            {
                int key = 0, key1 = 0, key2 = 0;
                dict.TryGetValue(a[i].ToString() + b[j].ToString(), out key);
                dict.TryGetValue("-" + b[j].ToString(), out key1);
                dict.TryGetValue(a[i].ToString() + "-", out key2);
                if (i == 0)
                    SQ[i, j] = key1;
                else if (j == 0)
                    SQ[i, j] = key2;
                else
                    SQ[i, j] = Math.Max(SQ[i - 1, j - 1] + key, Math.Max(SQ[i - 1, j] + key1, SQ[i, j - 1] + key2));
            }
        }
        for (int i = 0; i < a.Length; i++)
        {
            for (int j = 0; j < b.Length; j++)
            {
                Console.Write(SQ[i, j] + "   ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("Alignment Score : " + SQ[a.Length - 1, b.Length - 1]);            
        printAllAlignmentsWithHighestAlignmentScore();
        Console.Read();
    }

有人可以帮我实现 printAllAlignmentsWithHighestAlignmentScore() 函数吗?

最佳答案

最后,我有了工作代码来完成我想做的事情。 问题实际上是 Needleman–Wunsch algorithm 的细微变化。

代码:

class Program
{
    static Dictionary<string, int> dict;
    static void printAllAlignments(int[,] SQ, string a, string b, int p, int q, string str1, string str2){
        if (p == 0 || q == 0){
            while (p == 0 && q != 0){
                str1 = "-" + str1;
                str2 = b[--q]+str2;
            }
            while (q == 0 && p != 0){
                str1 = a[--p]+str1;
                str2 = '-' + str2;
            }
            Console.WriteLine("\n"+str1+"\n"+str2+"\n");
            return;
        }

        if (SQ[p, q] == (dict[a[p - 1] + b[q - 1].ToString()] + SQ[p - 1, q - 1]))
            printAllAlignments(SQ, a, b, p - 1, q - 1, a[p-1]+str1, b[q-1]+str2);

        if (SQ[p, q] == (dict[a[p - 1]+ "-"] + SQ[p - 1, q]))
            printAllAlignments(SQ, a, b, p - 1, q, a[p-1]+str1, "-"+str2);

        if (SQ[p, q] == (dict["-" + b[q-1]] + SQ[p, q - 1]))            
            printAllAlignments(SQ, a, b, p, q - 1, "-"+str1, b[q-1]+str2);


    }
    static void Main(string[] args)
    {
        //This has been assumed that the strings contain only A,C,G,T and -(?)..caps

        Console.WriteLine("Enter first string : ");
        string a = Console.ReadLine();         
        Console.WriteLine("Enter second string : ");
        string b = Console.ReadLine();          
        int[,] SQ = new int[a.Length+1, b.Length+1];

        #region Create Dictionary
        dict = new Dictionary<string, int>();
        dict.Add("AA", 5);
        dict.Add("AC", -1);
        dict.Add("AG", -2);
        dict.Add("AT", -1);
        dict.Add("A-", -3);

        dict.Add("CA", -1);
        dict.Add("CC", 5);
        dict.Add("CG", -3);
        dict.Add("CT", -2);
        dict.Add("C-", -4);

        dict.Add("GA", -2);
        dict.Add("GC", -3);
        dict.Add("GG", 5);
        dict.Add("GT", -2);
        dict.Add("G-", -2);

        dict.Add("TA", -1);
        dict.Add("TC", -2);
        dict.Add("TG", -2);
        dict.Add("TT", 5);
        dict.Add("T-", -1);

        dict.Add("-A", -3);
        dict.Add("-C", -4);
        dict.Add("-G", -2);
        dict.Add("-T", -1);
        dict.Add("--", 0);
        #endregion Create Dictionary

        SQ[0, 0] = 0;            
        for (int i = 1; i <= a.Length; i++)            
            SQ[i, 0] = dict["-" + a[i - 1].ToString()] + SQ[i - 1, 0];

        for (int i = 1; i <= b.Length; i++)
            SQ[0, i] = dict[b[i - 1].ToString() + "-"] + SQ[0, i - 1];

        for (int i = 1; i <= a.Length; i++)
            for (int j = 1; j <= b.Length; j++)
                SQ[i, j] = Math.Max(SQ[i - 1, j - 1] + dict[a[i-1].ToString() + b[j-1]], Math.Max(SQ[i - 1, j] + dict[a[i-1] + "-"], SQ[i, j - 1] + dict["-" + b[j-1]]));           


        Console.WriteLine("Max Alignment Score : " + SQ[a.Length, b.Length]);
        printAllAlignments(SQ, a, b, a.Length , b.Length,"","");
        Console.Read();
    }
}

关于c# - 打印具有最高分数的两个序列的所有比对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24929398/

相关文章:

c# - GridView 显示图像

c - 在 C 中取消引用结构的字段

java - 使用Iterator模式对n叉树进行前序/后序迭代遍历

arrays - 数组查询

php - 在 PHP 中对数组进行分组

c# - Unity 动画事件 - 未选择任何功能

c# - 用于开发的本地事件目录访问和管理?

c# - 如何从 C# 中的 C++/CLI dll 访问类型?

algorithm - 去除建筑物内不良的 GPS 信号

ruby-on-rails - 数组连接函数 - Ruby on Rails