我一直在使用正则表达式解决USACO处的“断项链”问题。虽然它适用于较小的输入,虽然是一个非常复杂的正则表达式,但它超过了较大输入的给定时间限制。
进一步输入,这是我使用的代码。我的问题是如何在仍然使用正则表达式的同时改进运行时。
非常感谢所有帮助。我是竞争性节目的新手,我真的被困了:s!
class beads {
public static void main(String[] args) throws IOException{
BufferedReader f = new BufferedReader(new FileReader("beads.in"));
//BufferedReader f = new BufferedReader(new FileReader("beads.txt"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("beads.out")));
int numBeads=Integer.parseInt(f.readLine());
String input=f.readLine();
String beadSequence=input.concat(input);
Pattern p1=Pattern.compile("^(w*r*)|^(w*b*)*");
Matcher m1=p1.matcher(input);
while(m1.find()){
String k=m1.group();
//System.out.println(k);
if(k.length()==numBeads){
out.println(k.length());
out.close();
System.exit(0);
}
}
//System.out.println(input);
//System.out.println(beadSequence);
Pattern p=Pattern.compile("(?=((b*w*)*b+w*r+(w*r*)*|(r*w*)*r+w*b+(w*b*)*))(^|(?<=w)b|(?<=b)w|(?<=w)r|(?<=r)w)");
Matcher m=p.matcher(beadSequence);
List<String> solutions=new ArrayList<String>();
int length=0;
while(m.find()){
String k=m.group(1);
//System.out.println(m.group(1));
if (k.length()>length)length=k.length();
}
out.println(length);
out.close();
System.exit(0);
}
}
答案 0 :(得分:2)
像(b*w*)*
这样的东西确实有很多可能匹配“b”和“w”的序列,这将导致catastrophic backtracking。
因为这会匹配这两个字母的任何序列,所以最好用字符类[bw]*
替换它。
所以你的表达式看起来像这样:
Pattern p=Pattern.compile("(?=([bw]*b+w*r+[rw]*|[rw]*r+w*b+[bw]*))(^|(?<=w)b|(?<=b)w|(?<=w)r|(?<=r)w)");
此表达式应该更快地匹配。
答案 1 :(得分:0)
有一个比目前给出的更简单的正则表达式
(?=([bw]*b+[rw]*|[rw]*r+[bw]*)).
您可以在debuggex上看到一个非常好的算法可视化。沿测试绳滑动黑色三角形,并注意第1组匹配。这是您的算法正在考虑确定长度的方法。请注意,示例字符串已经连接到自身,以便端点可以工作。