Java:根据多个规则在字符串中替换

Java:根据多个规则在字符串中替换,java,algorithm,Java,Algorithm,我有以下任务。有一根绳子。我必须按照6条规则进行替换,直到可以在字符串中进行替换 我找到的解决方案如下。它工作正常。问题是它的性能很低。我还可以如何根据多个规则进行替换?有算法吗 另外,该任务来自Codibility站点。我的解决方案有100%的正确性和25%的性能 class Test { private Map<String,String> rules; private void initRules(){ rules=new HashMap&l

我有以下任务。有一根绳子。我必须按照6条规则进行替换,直到可以在字符串中进行替换

我找到的解决方案如下。它工作正常。问题是它的性能很低。我还可以如何根据多个规则进行替换?有算法吗

另外,该任务来自Codibility站点。我的解决方案有100%的正确性和25%的性能

class Test {

    private Map<String,String> rules;

    private void initRules(){
        rules=new HashMap<>();
        rules.put("AB", "AA");
        rules.put("BA", "AA");
        rules.put("CB", "CC");
        rules.put("BC", "CC");
        rules.put("AA", "A");
        rules.put("CC", "C");
    }

    public String test(String S) {
        initRules();
        loop:while(true){
            String oldString=S;
            for (Map.Entry<String, String> rule : rules.entrySet())
            {
                S=S.replace(rule.getKey(), rule.getValue());
            }
            if (oldString==S){
                break loop;
            };
        }
        return S;
    }
}

 public class NewMain {

    public static void main(String[] args) {
        Test test=new Test();
        System.out.println("Result:"+test.test("ABBCC"));;
    }

}
类测试{
私有地图规则;
私有规则(){
rules=newhashmap();
规则。付诸表决(“AB”、“AA”);
规则。付诸表决(“BA”、“AA”);
规则。出售(“CB”、“CC”);
规则。付诸表决(“BC”、“CC”);
规则。付诸表决(“AA”、“A”);
规则。付诸表决(“CC”、“C”);
}
公共字符串测试(字符串S){
initRules();
循环:while(true){
字符串oldString=S;
for(Map.Entry规则:rules.entrySet())
{
S=S.replace(rule.getKey(),rule.getValue());
}
if(oldString==S){
断环;
};
}
返回S;
}
}
公共类纽曼{
公共静态void main(字符串[]args){
测试=新测试();
System.out.println(“结果:+test.test”(“ABBCC”);;
}
}

以下是您可以使用的算法:

假设:字符串仅由(A、B、C)组成

如果字符串仅由
B的
组成(无A/C),则输出=输入字符串

否则:

按以下方式分割字符串。如果子字符串由(B,a)或(B,C)组成,则将其除以。分别替换为A和C。这就是答案

让字符串为:“bbbababbccbbcacb”。这将分为:

“bbbababb”“CCBCBBC”“A”“CB”

这将导致输出字符串为:
ACAC


基本上,只要忽略所有的
B
,用
A
替换
A的集群,用
C
替换
C的集群,就可以实现一个递归算法。然后您可以减少规则并应用。例如
AB->AA,AA->A然后AB->A
那么答案就是

public static String stringReduce(String s){
  String transformed = s.replace("AA", "A").replace("CC", "C")
   .replace("BC", "C").replace("CB", "C").replace("BA", "A")
   .replace("AB", "A");

  if(transformed.equals(s)){
    return transformed;
  }
  else{
    return stringReduce(transformed);
  }
}

我的python解决方案使用正则表达式

说明:如果输入为“ABACABCA”

首先迭代:将替换AB->A,AA->A,BC->C。strng的值为“AACACA”

第二次迭代时:将替换AA->A。strng的值为“ACACA”

第三次迭代时:无需替换,因此将退出并返回最终替换字符串(strng)。 如果需要任何改进或更正,请告诉我

def solution(strng):
  prevS=""
  subst={"AB":"A","BA":"A","CB":"C","BC":"C","AA":"A","CC":"C"}
  subs=lambda st:subst[st.group(0)]
  while prevS!=strng:
      prevS=strng
      strng=re.sub(r'(([A][BA])|([B][A])|([CB][C])|([C][B]))',subs,strng)
  return strng

我更喜欢执行while循环而不是递归:

答案如下:

public String stringReduce(String input) {
    String previous;
    do {
        previous = input;
        input = input.replace("AA", "A").replace("CC", "C").replace("BC", "C").replace("CB", "C")
                .replace("BA", "A").replace("AB", "A");
    } while (!previous.equals(input));
    return input;
}

我遵循@vish4071的推理

我只寻找“B”和“A”的子字符串,我知道该段将变成“A”。仅子字符串“B”和“C”相同

“BAABBAB”变为“A”是因为
将(“AB”替换为“AA”)、将(“BA”替换为“AA”)、将(“AA”替换为“A”)

输入:“bbbababbccbcbbcacb”

“bbbababb”“CCBCBBC”“A”“CB”

A“C”A“C”

输出:“ACAC”

当子字符串“A”从/变为“C”时,这两种算法保持跟踪。我附加已知的前一个字符。因为更改检测是基于“A”到“C”或“C”到“A”的,所以您不需要在第一个子字符串中使用前面的字符。循环结束后,必须追加上一个字符

运行时复杂性:O(n)

空间复杂度:O(1)

下面是Java的实现

  public static String solution(String S) {

        final char C = 'C';
        final char A = 'A';

        // if contains only B return itself
        if(!S.contains("A") || !S.contains("C")) return S;

    String res = "";
    boolean hasLetterChanged = false;
    char prevChar = 'D';
    for(char c : S.toCharArray()){
        if (c == A){
            if (prevChar == C){hasLetterChanged = true;}
        }else if(c == C){
            if (prevChar == A){hasLetterChanged = true;}
        }
        if(hasLetterChanged){
            res = res + prevChar;
            hasLetterChanged = false;
        }
        if(c == A || c == C){
            prevChar = c;
        }
    }

    return res + prevChar;
}
下面是Python 2.7(与3x兼容)中的实现

这是我的C#解决方案:

public static string solution(string S)
    {
        return Getreplace(S);
    }

    public static string Getreplace(string input)
    {
        string retval = input.Replace("AB", "AA")
                    .Replace("BA", "AA")
                    .Replace("CB", "CC")
                    .Replace("BC", "CC")
                    .Replace("AA", "A")
                    .Replace("CC", "C");

        if (input == retval)
            return retval;
        else
            return Getreplace(retval);
    }

是否对规则有偏好?@vish4071否,任何规则都可以随机选取。我要做的一件事是检查字符串是否包含我要替换的子字符串。如果子字符串不存在,则无需调用
replace(…)
\n您可以做的一件事是将所有规则替换为:((“AA,AB,BA”->“A”和“BC,CC,CB”->“C”),只是为了更清楚,您可以将if(oldString==S)替换为您也应该使用的(虽然为true)。对于字符串比较,还可以使用等于来表示“o/p”和“i/p”字符串?输出和输入字符串。对不起,我的速记符号。我会编辑它。我应该猜到的。如示例所示,分割字符串的有效方法是什么?@Olegabrazhev只需一次解析一个字符。如果字符串不是全部“B”,请删除所有B,用A替换A的簇,用C替换C的簇。这可能会给出正确的答案,但我很确定这不会在Codibility的性能测试中实现。上次我用递归函数尝试它时,在很长的字符串上得到了一个StackOverflower错误。
public static string solution(string S)
    {
        return Getreplace(S);
    }

    public static string Getreplace(string input)
    {
        string retval = input.Replace("AB", "AA")
                    .Replace("BA", "AA")
                    .Replace("CB", "CC")
                    .Replace("BC", "CC")
                    .Replace("AA", "A")
                    .Replace("CC", "C");

        if (input == retval)
            return retval;
        else
            return Getreplace(retval);
    }