Java 部分匹配长度-字符串相似性的正则表达式
假设我有一个字符串“Torcellite”和另一个字符串“Tor”-这两个字符串的相似长度是3,因为它们都以“Tor”开头。现在,另一个字符串“christmas”和“mas”的相似性为0,因为它们不以相同的字符集开头 在这两种情况下,第二个字符串都是第一个字符串的后缀 更清楚的例子是: 字符串长度:1到10^5 字符串: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
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),在我的电脑中执行时间小于时间20mspublic 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;i
0&&!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(); 返回计数; }
示例中,我推断您正在尝试查找与原始字符串开头匹配的所有子字符串。这可以通过单个正则表达式完成,有点类似于您提出的模式。当然,正则表达式的长度将与原始字符串成比例。rabaabc
(?=(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; } }