【问题标题】:finding a supersequence of DNA Java寻找 DNA Java 的超序列
【发布时间】:2013-10-21 05:02:21
【问题描述】:

我正在为“查找超序列”算法而苦苦挣扎。

输入是一组字符串

String A = "caagccacctacatca";
String B = "cgagccatccgtaaagttg";
String C = "agaacctgctaaatgctaga";

结果将是正确对齐的字符串集(下一步应该是合并)

String E = "ca ag cca  cc ta    cat  c a";
String F = "c gag ccat ccgtaaa g  tt  g";
String G = " aga acc tgc  taaatgc t a ga";

感谢您的任何建议(我在这个任务上坐了一天多)

合并后的超字符串将是

cagagaccatgccgtaaatgcattacga

“这种情况”中超序列的定义类似于

当且仅当字符串 R 中的所有字符都按照它们在输入序列 R 中出现的顺序出现在超序列 S 中时,字符串 R 才包含在超序列 S 中。


我尝试过的“解决方案”(同样是错误的做法)是:

public class Solution4
{
    static  boolean[][] map = null;
    static int size = 0;

    public static void main(String[] args)
    {
        String A = "caagccacctacatca";
        String B = "cgagccatccgtaaagttg";
        String C = "agaacctgctaaatgctaga";

        Stack data = new Stack();
        data.push(A);
        data.push(B);
        data.push(C);


        Stack clone1 = data.clone();
        Stack clone2 = data.clone();

        int length  =  26;
        size        =  max_size(data);

        System.out.println(size+" "+length);
        map = new boolean[26][size];

        char[] result = new char[size];

        HashSet<String> chunks = new HashSet<String>();
        while(!clone1.isEmpty())
        {
            String a = clone1.pop();

            char[] residue = make_residue(a);

            System.out.println("---");
            System.out.println("OLD     : "+a);
            System.out.println("RESIDUE : "+String.valueOf(residue));


            String[] r = String.valueOf(residue).split(" ");

            for(int i=0; i<r.length; i++)
            {
                if(r[i].equals(" ")) continue;
                //chunks.add(spaces.substring(0,i)+r[i]);
                chunks.add(r[i]);
            }
        }

        for(String chunk : chunks)
        {
            System.out.println("CHUNK   : "+chunk);
        }
    }

    static char[] make_residue(String candidate)
    {
        char[] result = new char[size];
        for(int i=0; i<candidate.length(); i++)
        {
            int pos = find_position_for(candidate.charAt(i),i);
            for(int j=i; j<pos; j++) result[j]=' ';
            if(pos==-1) result[candidate.length()-1] = candidate.charAt(i);
            else        result[pos] = candidate.charAt(i);
        }
        return result;
    }

    static int find_position_for(char character, int offset)
    {
        character-=((int)'a');

        for(int i=offset; i<size; i++)
        {
        //  System.out.println("checking "+String.valueOf((char)(character+((int)'a')))+" at "+i);
            if(!map[character][i])
            {
                map[character][i]=true;
                return i;
            }
        }
        return -1;
    }

    static String move_right(String a, int from)
    {
        return a.substring(0, from)+" "+a.substring(from);  
    }


    static boolean taken(int character, int position)
    { return map[character][position]; }

    static void take(char character, int position)
    {
        //System.out.println("taking "+String.valueOf(character)+" at "+position+" (char_index-"+(character-((int)'a'))+")");
        map[character-((int)'a')][position]=true;
    }

    static int max_size(Stack stack)
    {
        int max=0;
        while(!stack.isEmpty())
        {
            String s = stack.pop();
            if(s.length()>max) max=s.length();
        }

        return max;
    }

}

【问题讨论】:

  • 您尝试过什么,遇到过什么问题?我们不知道你不知道什么。
  • 代码会太长而且它是/现在是“错误的方法”。
  • “正确对齐”是什么意思?
  • 嘿,你如何决定应该首先添加哪个字符.. 取序列中的前 3-4 个字符,我想出了两个可能的合并:、, 结果将开始为: 或 , , 在此如果结果将开始为: 优先考虑哪一个,还是没有区别?
  • Amol:只要超字符串有效,哪个字符在前并不重要。彼得:通过正确对齐,重叠子序列“在同一列”

标签: java algorithm substring


【解决方案1】:

你可以试试这样找到最短的组合

static final char[] CHARS = "acgt".toCharArray();

public static void main(String[] ignored) {
    String A = "caagccacctacatca";
    String B = "cgagccatccgtaaagttg";
    String C = "agaacctgctaaatgctaga";
    String expected = "cagagaccatgccgtaaatgcattacga";

    List<String> ABC = new Combination(A, B, C).findShortest();
    System.out.println("expected: " + expected.length());
    System.out.println("Merged: " + ABC.get(0).length() + " " + ABC);
}

static class Combination {
    int shortest = Integer.MAX_VALUE;
    List<String> shortestStr = new ArrayList<>();
    char[][] chars;
    int[] pos;
    int count = 0;

    Combination(String... strs) {
        chars = new char[strs.length][];
        pos = new int[strs.length];
        for (int i = 0; i < strs.length; i++) {
            chars[i] = strs[i].toCharArray();
        }
    }

    public List<String> findShortest() {
        findShortest0(new StringBuilder(), pos);
        return shortestStr;
    }

    private void findShortest0(StringBuilder sb, int[] pos) {
        if (allDone(pos)) {
            if (sb.length() < shortest) {
                shortestStr.clear();
                shortest = sb.length();
            }
            if (sb.length() <= shortest)
                shortestStr.add(sb.toString());
            count++;
            if (++count % 100 == 1)
            System.out.println("Searched " + count + " shortest " + shortest);
            return;
        }
        if (sb.length() + maxLeft(pos) > shortest)
            return;
        int[] pos2 = new int[pos.length];
        int i = sb.length();
        sb.append(' ');
        for (char c : CHARS) {
            if (!tryChar(pos, pos2, c)) continue;
            sb.setCharAt(i, c);
            findShortest0(sb, pos2);
        }
        sb.setLength(i);
    }

    private int maxLeft(int[] pos) {
        int maxLeft = 0;
        for (int i = 0; i < pos.length; i++) {
            int left = chars[i].length - pos[i];
            if (left > maxLeft)
                maxLeft = left;
        }
        return maxLeft;
    }

    private boolean allDone(int[] pos) {
        for (int i = 0; i < chars.length; i++)
            if (pos[i] < chars[i].length)
                return false;
        return true;
    }

    private boolean tryChar(int[] pos, int[] pos2, char c) {
        boolean matched = false;
        for (int i = 0; i < chars.length; i++) {
            pos2[i] = pos[i];
            if (pos[i] >= chars[i].length) continue;
            if (chars[i][pos[i]] == c) {
                pos2[i]++;
                matched = true;
            }

        }
        return matched;
    }
}

打印出许多比建议的更短的解决方案。

预计:28
合并:27 [acgaagccatccgctaaatgctatcga,acgaagccatccgctaaatgctatgca,acgaagccatccgctaacagtgctaga,acgaagccatccgctaacatgctatga,acgaagccatccgctaacatgcttaga,acgaagccatccgctaacatgtctaga,acgaagccatccgctacaagtgctaga,acgaagccatccgctacaatgctatga,acgaagccatccgctacaatgcttaga,acgaagccatccgctacaatgtctaga,acgaagccatcgcgtaaatgctatcga,acgaagccatcgcgtaaatgctatgca,acgaagccatcgcgtaacagtgctaga,acgaagccatcgcgtaacatgctatga,acgaagccatcgcgtaacatgcttaga,acgaagccatcgcgtaacatgtctaga,acgaagccatcgcgtacaagtgctaga,acgaagccatcgcgtacaatgctatga,acgaagccatcgcgtacaatgcttaga,acgaagccatcgcgtacaatgtctaga,acgaagccatgccgtaaatgctatcga,acgaagccatgccgtaaatgctatgca,acgaagccatgccgtaacagtgctaga, acgaagccatgccgtaacatgctatga,acgaagccatgccgtaacatgcttaga,acgaagccatgccgtaacatgtctaga,acgaagccatgccgtacaagtgctaga,acgaagccatgccgtacaatgctatga,acgaagccatgccgtacaatgcttaga,acgaagccatgccgtacaatgtctaga,cagaagccatccgctaaatgctatcga,cagaagccatccgctaaatgctatgca,cagaagccatccgctaacagtgctaga,cagaagccatccgctaacatgctatga,CA gaagccatccgctaacatgcttaga,cagaagccatccgctaacatgtctaga,cagaagccatccgctacaagtgctaga,cagaagccatccgctacaatgctatga,cagaagccatccgctacaatgcttaga,cagaagccatccgctacaatgtctaga,cagaagccatcgcgtaaatgctatcga,cagaagccatcgcgtaaatgctatgca,cagaagccatcgcgtaacagtgctaga,cagaagccatcgcgtaacatgctatga,cagaagccatcgcgtaacatgcttaga,cagaagccatcgcgtaacatgtctaga,cagaagccatcgcgtacaagtgctaga,cagaagccatcgcgtacaatgctatga,cagaagccatcgcgtacaatgcttaga,cagaagccatcgcgtacaatgtctaga,cagaagccatgccgtaaatgctatcga,cagaagccatgccgtaaatgctatgca,cagaagccatgccgtaacagtgctaga,cagaagccatgccgtaacatgctatga,cagaagccatgccgtaacatgcttaga,cagaagccatgccgtaacatgtctaga,cagaagccatgccgtacaagtgctaga,cagaagccatgccgtacaatgctatga,cagaagccatgccgtacaatgcttaga, cagaagccatgccgtacaatgtctaga, cagagaccatccgctaaatgctatcga, cagagaccatccgctaaatgctatgca, cagagaccatccgctaacagtgctaga, cagagaccatccgctaacatgctatga, cagagaccatccgctaacatgcttaga, cagagaccatccgctaacatgtctaga, cagagacccatccgctacacacaccatgctaga, cagagacaccatcgctagat caatgcttaga,cagagaccatccgctacaatgtctaga,cagagaccatcgcgtaaatgctatcga,cagagaccatcgcgtaaatgctatgca,cagagaccatcgcgtaacagtgctaga,cagagaccatcgcgtaacatgctatga,cagagaccatcgcgtaacatgcttaga,cagagaccatcgcgtaacatgtctaga,cagagaccatcgcgtacaagtgctaga,cagagaccatcgcgtacaatgctatga,cagagaccatcgcgtacaatgcttaga,cagagaccatcgcgtacaatgtctaga,cagagaccatgccgtaaatgctatcga,cagagaccatgccgtaaatgctatgca,cagagaccatgccgtaacagtgctaga,cagagaccatgccgtaacatgctatga,cagagaccatgccgtaacatgcttaga,cagagaccatgccgtaacatgtctaga,cagagaccatgccgtacaagtgctaga,cagagaccatgccgtacaatgctatga,cagagaccatgccgtacaatgcttaga,cagagaccatgccgtacaatgtctaga,cagagccatcctagctaaagtgctaga,cagagccatcctagctaaatgctatga,cagagccatcctagctaaatgcttaga, cagagccatcctagctaaatgtctaga,cagagccatcctgactaaagtgctaga,cagagccatcctgactaaatgctatga,cagagccatcctgactaaatgcttaga,cagagccatcctgactaaatgtctaga,cagagccatcctgctaaatgctatcga,cagagccatcctgctaaatgctatgca,cagagccatcctgctaacagtgctaga,cagagccatcctgctaacatgctatga,cagagccatcctgctaacatgcttaga,C agagccatcctgctaacatgtctaga, cagagccatcctgctacaagtgctaga, cagagccatcctgctacaatgctatga, cagagccatcctgctacaatgcttaga, cagagccatcctgctacaatgtctaga]

【讨论】:

  • 嘿,只是一个小建议......不会添加“break”,在设置“found = true”之后会更好。既然我们找到了位置 i 的字符,为什么要遍历其他字符串?
  • 我认为合并在这里不是问题。问题是找到最小的“对齐”分区,最后找到最小的超序列。
  • @ŁukaszRzeszotarski 我同意,我想我现在理解了这个问题,看来你需要先知道合并的字符串是什么,这样你才能推导出子序列。
  • @PeterLawrey 不完全是,因为找到合并的序列是此任务的目标。看我的回答。
  • @ŁukaszRzeszotarski 在我的解决方案中,我找到了最短的组合,您可以从中确定“正确对齐”的字符串
【解决方案2】:

找到任何常见的超序列并不是一项艰巨的任务:

在您的示例中,可能的解决方案类似于:

公共类 SuperSequenceTest {

public static void main(String[] args) {
    String A = "caagccacctacatca";
    String B = "cgagccatccgtaaagttg";
    String C = "agaacctgctaaatgctaga";

    int iA = 0;
    int iB = 0;
    int iC = 0;

    char[] a = A.toCharArray();
    char[] b = B.toCharArray();
    char[] c = C.toCharArray();


    StringBuilder sb = new StringBuilder();

    while (iA < a.length || iB < b.length || iC < c.length) {
        if (iA < a.length && iB < b.length && iC < c.length && (a[iA] == b[iB]) && (a[iA] == c[iC])) {
            sb.append(a[iA]);
            iA++;
            iB++;
            iC++;
        }
        else if (iA < a.length && iB < b.length && a[iA] == b[iB]) {
            sb.append(a[iA]);
            iA++;
            iB++;
        }
        else if (iA < a.length && iC < c.length && a[iA] == c[iC]) {
            sb.append(a[iA]);
            iA++;
            iC++;
        }
        else if (iB < b.length && iC < c.length && b[iB] == c[iC]) {
            sb.append(b[iB]);
            iB++;
            iC++;
        } else {
            if (iC < c.length) {
                sb.append(c[iC]);
                iC++;
            }
            else if (iB < b.length) {
                sb.append(b[iB]);
                iB++;
            } else if (iA < a.length) {
                sb.append(a[iA]);
                iA++;
            }
        }
    }
    System.out.println("SUPERSEQUENCE " + sb.toString());
}

}

然而真正要解决的问题是找到Shortest Common Supersequence http://en.wikipedia.org/wiki/Shortest_common_supersequence的已知问题的解决方案, 这并不容易。

有很多关于这个话题的研究。

例如:

http://www.csd.uwo.ca/~lila/pdfs/Towards%20a%20DNA%20solution%20to%20the%20Shortest%20Common%20Superstring%20Problem.pdf

http://www.ncbi.nlm.nih.gov/pubmed/14534185

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 2020-04-03
    相关资源
    最近更新 更多