模式搜索算法

时间:2015-12-29 23:17:52

标签: java regex algorithm

我的信很少,想找到经常发生的模式。

我有以下信件:

 ---------TAAA-GAGAG----T--T-------T
 -------------T------A---------T----
 ----------AAA-GAGAG---C-----------T
 ------C------------T-A----T-----TA-
 -----AC----------------TT--------C-
 -------------------T---------------
 ---A---------------T---------------
 -------------------------T----T----
 ------C---------------------T-----T
 ----------AAA-GAGAG---C------------
 ----A--------------------T-------A-
 --------G-G-----------G-------T----
 ----A--------------------T---------
 ---------T-------------------------
 -----AC------T--------------------T
 --GA-G------------GT--------------T
 -----A--G-AAA-GAGAG-AA-------------
 -----------------------------------
 -T-------C-G-------T---TT------T--T
 TT-----------------T---------------
 -------------------T---TT-T--------
 ---A----G------------A--------T----
 -----------------------------------
 -------T--AA--G-GAG---C------------
 -T-A----------------A--------------
 ------------T------------------T---
 -----------G-----------------------
 --G-A------------------C---T---T---
 ----A---G---A-------A------T-------
 --------G-------------------T-----T
 -TG--------A---------A-T-----------
 --G--A--------GAGAG---CT-----------
 ---A-------G------------T----G---A-
 T-------G----T---------------------
 -T----C-GCAA--GAGAG-A-C-----T--TT--
 -----A----AAA-GAGAG-A-T------G---A-
 -T---------G-----------------------
 ---A---T---------------------G-----
 ---A---------T-------A---T---A---A-
 -----------------------------------
 TC--A----T----------G-------T-T--G-
 -T----CT---G-T-----T-A----T-T--T---
 -------------T-----TA------------A-
 --G----T-----------------T-T--T----
 ---A------AA--GAGAG---C-----T------
 --------------GAGAG-A-C------------
 ----------AA--GAGAG---C-G----------

正如您所看到的,中间有一个模式:" GAGAG",所以我可以说G + A + G + A + G来自相同的数据。

我想拆分那些行和组。

错误的案例。第一行有T + A + A + A但另一行不与 T + A + A + A,只有A + A + A总是在一起。所以在这种情况下,T和A不是组。

任何人都知道这种相关算法或如何找到模式。

我尝试使用Java编程。

谢谢。

更新-----------------------------------------

1)模式需要的最小长度是多少? - 两个。并且不必是连续的职位。

2)可以" - "符号是模式的一部分? - 不。" - "意味着这个位置可以是任何字符,例如" undefined"。

3)模式应该位于每条线的完全相同的索引上吗? - 是(但有些行可能是 - )

4)模式发生的最小数量是多少(2个出现的次数是多少?) - 这还没有确定,只是想先找到最多的出现位置,以后会发现最佳出现位置。

3 个答案:

答案 0 :(得分:2)

您可以创建https://en.wikipedia.org/wiki/Suffix_arrayhttps://en.wikipedia.org/wiki/LCP_array并查看最不常用的前缀数组以查找长公共前缀,这意味着再次出现了子字符串。

答案 1 :(得分:1)

我认为您应该使用trie structure来解决此任务。我将描述算法覆盖从索引0开始的所有子串 - 然后可以应用相同的算法从其他索引开始检查子串。

步骤:

  1. 初始化空trie
  2. 对于每行初始化集合,引用trie节点(最初每个集合都引用了trie root)。
  3. 对于每行初始化数组以跟踪要检查的当前索引
  4. 选择下一行(最初的第一行)。如果所有线路流程 - 转到7)
  5. 检查当前的跟踪索引是否不是" - "如果是这样 - 对于附加到当前行的集合中的每个引用(如上所述),使用计数器1为该行的当前字母创建子节点(如果节点已存在 - 将计数器增加1)。将所有新/更新节点捕获到集合中。然后将附加到行的set替换为new set并增加line的索引并返回到第4点。
  6. 检查当前要跟踪的索引是否为" - "。如果是这样,请跳过这条线。
  7. 对于作为指令6的一部分跳过的每一行都这样做:
    • 增加附加到当前行的集合中节点的所有子节点。
    • 表示新的子节点集增加。
    • 增加当前行的索引
  8. 注意:一旦处理到某个深度(比如3个符号),算法就可以停止。具有最高值的trie中的节点将是最常见的模式。你想要拿同样长度的最长的那个。

    复杂度:

    O(N M A ^ K)其中N - 行数,M - 每行中的字母数,A - 字母大小(例如遇到的不同字母数)K - 最大模式要检查的长度。

答案 2 :(得分:1)

你可以使用这个算法我逐行汇总,然后迭代模式并检查它们是否与其他线条模式匹配。

Pattern[] getPatternsForLine(String line){
ArrayList<Pattern> patterns=new ArrayList<Pattern>();
String temp=""; //what we will store the current pattern int
boolean inPattern=false;
for(char character:line.toCharArray()){
    if(!"-".equals(character)){
        temp=temp+character;
    }else{
        if(inPattern){
            boolean existsInLine=false;//already exists?
            for(Pattern p:patterns){
                if(p.pattern.equals(temp)){
                    p.occurences++;
                    existsInLine=true;
                    break;
                }
            }
            if(!existsInLine)
                patterns.add(new Pattern(temp));
        }
        inPattern=false;
        temp="";
    }
}
return patterns.toArray();
}

class Pattern{
    public String pattern;
    public int occurences;
    public Pattern(String pattern){
        this.pattern=pattern;
        occurences=1;
    }
}