Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 部分匹配长度-字符串相似性的正则表达式_Java_Regex_String_Pattern Matching - Fatal编程技术网

Java 部分匹配长度-字符串相似性的正则表达式

Java 部分匹配长度-字符串相似性的正则表达式,java,regex,string,pattern-matching,Java,Regex,String,Pattern Matching,假设我有一个字符串“Torcellite”和另一个字符串“Tor”-这两个字符串的相似长度是3,因为它们都以“Tor”开头。现在,另一个字符串“christmas”和“mas”的相似性为0,因为它们不以相同的字符集开头 在这两种情况下,第二个字符串都是第一个字符串的后缀 更清楚的例子是: 字符串长度:1到10^5 字符串:ababc 后缀:abaabc,baabc,aabc,abc,bc,c 相似性:ababc,无,a,ab,无,无 相似长度:6,0,1,2,0,0 回答:6+0+1+2+0+0

假设我有一个字符串“Torcellite”和另一个字符串“Tor”-这两个字符串的相似长度是3,因为它们都以“Tor”开头。现在,另一个字符串“christmas”和“mas”的相似性为0,因为它们不以相同的字符集开头

在这两种情况下,第二个字符串都是第一个字符串的后缀

更清楚的例子是:

字符串长度:1到10^5

字符串:
ababc

后缀:
abaabc
baabc
aabc
abc
bc
c

相似性:
ababc
,无,
a
ab
,无,无

相似长度:6,0,1,2,0,0

回答:6+0+1+2+0+0=9

我使用regex查找这些部分后缀匹配的逻辑效率很低

算法:

  • 查找给定字符串的所有子字符串
  • 从后缀的子字符串中创建一个模式

    for(int i=1; i<substrings[i].length; i++) {
        Pattern p = Pattern.compile("^"+substrings[i].substring(0, i));
        Matcher m = p.find(string); //the given string for which similarities need to be  calculated
        if(m.find())
            similaryLengths +=  i;
    }
    

    for(int i=1;i这就是我将如何执行您上面描述的操作。我不知道这应该完成什么,但是由于您指定了只需要匹配字符串的开头,即使它是O(n^2),大多数情况下它不会在接近n的全长的任何地方运行。最坏的情况显然是类似于“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    我认为没有必要为严格的前缀匹配生成和编译正则表达式,我是否错过了要点

    int similarity(String input) {
        int count = 0;
        for (int i = 0; i < input.length() ; i++) {
            String sub = input.substring(i);
            for (int j = 0; j < sub.length(); j++) {
                if (input.charAt(j) != sub.charAt(j))
                    break;
                count++;
            }
        }
        return count;
    }
    
    int相似性(字符串输入){
    整数计数=0;
    对于(int i=0;i
    这在您的数据集上是如何执行的

    int sum = s.length;
    for (int i = 1; i < s.length; i++) {
        for (int j = i; j < s.length; j++) {
            for (int k = 0; k < s.length - j; k++) {
                if (s.charAt(i+k) != s.charAt(j+k)) break;
                sum++;
            }
        }
    }
    
    int sum=s.length;
    对于(int i=1;i

    您可以找到下一个出现的s.charAt(0)而不是迭代i。

    Valdar Moridin已经发布的Simliar算法,但不需要创建子字符串(每次调用
    substring
    都将创建一个新的
    字符串
    对象,该对象包含其源的
    char[]
    指定范围的副本)。这不会提高时间复杂度,但可能会降低总运行时间(常数因子):

    public static int partialSuffixMatch(CharSequence input) {
        int count = input.length();
        for (int i = 1; i < input.length(); i++) {
            for (int a = 0, b = i; b < input.length(); a++, b++) {
                if (input.charAt(a) != input.charAt(b))
                    break;
                count++;
            }
        }
        return count;
    }
    
    public static int partialSuffixMatch(字符序列输入){
    int count=input.length();
    对于(int i=1;i

    在短暂的热身后,此算法在我的计算机上处理一个
    字符串,在大约40毫秒内处理10000个相等字符,在大约4秒钟内处理100000个相等字符。

    请尝试以下方法。我已经测试了此方法。
    任何输入字符串(长度为1~10^5),在我的电脑中执行时间小于时间20ms

    public static int oneTry(CharSequence input) {
        int tail = input.length();
        for (int i = 1; i < input.length(); i++) {
            if (input.charAt(i) == input.charAt(0)) {
                tail = i;
                break;
            }
        }
    
        int count = 0;
    
        int head = 0;
        int next = 0;
        int base = 0;
        int two = -1;
        boolean start = false;
        boolean end = false;
        for (int i = tail; i < input.length(); i++) {
            if (input.charAt(i) == input.charAt(next)) {
    
                count++;
    
                if (next>0 && !start && input.charAt(i) == input.charAt(0)) {
                    base = 1;
                    start = true;
                }
    
                if (start) {
                    if (!end && input.charAt(i) == input.charAt(head)) {
                        count = count + base;
                        head++;
                        head = head < tail ? head : 0;
                        if(head == 0) {
                            base++;
                        }
                    } else {
                        end = true;
                    }
    
                    if(end) {
                        if(two <0 && input.charAt(i) == input.charAt(0)) {
                            two = i;
                        }
                    }
                }
    
                next++;
    
                if(i==input.length()-1 && two > 0) {
                    i = two - 1;
    
                    next = 0;
                    base = 0;
                    two = -1;
                    start = false;
                    end = false;
                    head = 0;
                }
    
            } else {
                if(two > 0) {
                    i = two - 1;
    
                    next = 0;
                    base = 0;
                    two = -1;
                    start = false;
                    end = false;
                    head = 0;
                } else {
                    if(end || !start) {
                        if(input.charAt(i) == input.charAt(0)) i--;
    
                        next = 0;
                        base = 0;
                        two = -1;
                        start = false;
                        end = false;
                        head = 0;
                    } else {
                        i--;
    
                        next = next - tail;
                        base = base -1;
                        two = -1;
                        start = base==0 ? false : true;
                        end = false;
                        //head = 0;
                    }                   
                }
            }
        }
        count = count + input.length();
        return count;
    }
    
    publicstaticintonetry(字符序列输入){
    int tail=input.length();
    对于(int i=1;i0&&!start&&input.charAt(i)=input.charAt(0)){
    基数=1;
    开始=真;
    }
    如果(启动){
    如果(!end&&input.charAt(i)=input.charAt(head)){
    计数=计数+基数;
    head++;
    头=头<尾?头:0;
    如果(头==0){
    base++;
    }
    }否则{
    结束=真;
    }
    若(完){
    如果(两个0){
    i=2-1;
    next=0;
    基数=0;
    二=-1;
    开始=错误;
    结束=假;
    水头=0;
    }
    }否则{
    如果(两个>0){
    i=2-1;
    next=0;
    基数=0;
    二=-1;
    开始=错误;
    结束=假;
    水头=0;
    }否则{
    如果(结束| |!开始){
    如果(输入字符(i)=输入字符(0))i--;
    next=0;
    基数=0;
    二=-1;
    开始=错误;
    结束=假;
    水头=0;
    }否则{
    我--;
    下一个=下一个-尾部;
    基数=基数-1;
    二=-1;
    start=base==0?false:true;
    结束=假;
    //水头=0;
    }                   
    }
    }
    }
    count=count+input.length();
    返回计数;
    }
    
    abaabc
    示例中,我推断您正在尝试查找与原始字符串开头匹配的所有子字符串。这可以通过单个正则表达式完成,有点类似于您提出的模式。当然,正则表达式的长度将与原始字符串成比例。r
    (?=(a(?:b(?:c(?:d(?:ef?)?)?)?)?))
    
    function generateRegex(string input)
    {
        return input.substring(0, 1) +
               (input.length > 2 ? "(?:" + generateRegex(input.substring(1)) + ")" : input.substring(1)) +
               "?";
    }
    
    string myRegex = "(?=(" + generateRegex(myInput) + "))";
    
        public static List<ANode> anodes = null;
        public static List<ANode> tnodes = null;
        public static void checkANodes(CharSequence input, int num) {
            tnodes = new Vector<ANode>(); 
            for(int i=anodes.size()-1; i>=0; i--) {
                ANode anode = anodes.get(i);
                if(input.charAt(num) == input.charAt(num-anode.pos)) {
                    tnodes.add(anode);
                }else {
                    if(tnodes.size() > 0) {
                        // ok to do the changes
                        ANode after = tnodes.get(tnodes.size()-1);
                        tnodes.remove(after);
                        if(after.c > 1) {
                            tnodes.add(new ANode(after.pos + after.shift, after.shift ,after.c-1)); 
                            tnodes.add(new ANode(after.pos, after.pos-anode.pos + anode.shift,1));
                        }else {
                            tnodes.add(new ANode(after.pos, after.pos-anode.pos + anode.shift,1));  
                        }
                    }
                }
            }
    
            anodes.clear();
            for(int i=tnodes.size() - 1; i >= 0; i--) {
                anodes.add(tnodes.get(i));
            }
        }
    
        public static int secondTry(CharSequence input) {
            anodes = new Vector<ANode>();
    
            int start = 0;
            for (int i = 1; i < input.length(); i++) {
                if (input.charAt(i) == input.charAt(0)) {
                    start = i;
                    break;
                }
            }
    
            int count = 0;
            int base = 0;
            for (int i = start; i < input.length(); i++) {
                checkANodes(input, i);
                if(input.charAt(0) == input.charAt(i)) {
                    if(anodes.size() == 0) {
                        anodes.add(new ANode(i,  i, 1));
                    }else {
                        ANode last = anodes.get(anodes.size()-1);
                        int shift = i - last.pos;
                        int mod = shift % last.shift;
                        if(mod == 0) {
                            last.c++;
                        }else {
                            anodes.add(new ANode(i, mod, 1));
                        }
                    }
                }
    
                base = 0;
                for(ANode anode : anodes) {
                    base = base + anode.c;
                }           
                count = count + base;
            }
    
            count = count + input.length();
            return count;
        }
    
    public class ANode {
        public int pos = 0;
        public int c = 1;
        public int shift = 0;
    
        public ANode(int pos, int shift, int c) {
            this.pos = pos;
            this.shift = shift;
            this.c = c;
        }
    }