Java 如何修复递归字符串检查

Java 如何修复递归字符串检查,java,string,recursion,Java,String,Recursion,在第一条输入线上会有一条秘密信息(数字序列)。e、 g.1122 在第二个输入行中,将使用密码对给定格式的消息进行编码: “{LetterX}{CodeForX}{LetterY}{CodeForY}…”其中原始邮件中的每个字母x将使用密码中的CodeForX进行编码。e、 g.A1B12C11D2 打印可编码为给定密码的所有可能原始邮件的编号。在下一行中,打印这些消息。 例如 3->AADD ABD CDD 我的想法是检查消息中是否存在字符串开头的任何字母代码(如“1”、“12”等),如果发现

在第一条输入线上会有一条秘密信息(数字序列)。e、 g.1122

在第二个输入行中,将使用密码对给定格式的消息进行编码:
“{LetterX}{CodeForX}{LetterY}{CodeForY}…”
其中原始邮件中的每个字母x将使用密码中的CodeForX进行编码。e、 g.A1B12C11D2

打印可编码为给定密码的所有可能原始邮件的编号。在下一行中,打印这些消息。 例如 3->AADD ABD CDD

我的想法是检查消息中是否存在字符串开头的任何字母代码(如“1”、“12”等),如果发现了,则将其从消息中删除,并递归进行,直到到达字符串结尾

public class Main {
static List<String> gList = new ArrayList<>();

public static void main(String[] args) throws IOException {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String message = in.readLine();     // "1122"
    String codeStr = in.readLine();     // "A1B12C11D2"
// SPLITTING LETTERS FROM CODES:
    String [] secretCode = codeStr.split("[^A-Z0-9]+|(?<=[A-Z])(?=[0-9])|(?<=[0-9])(?=[A-Z])");
    int n = secretCode.length / 2;
    String [] letters = new String [n];  // [A  B   C   D]
    String [] codes = new String [n];    // [1  12  11  2]
    for (int i = 0; i < 2 * n; i+=2) {
        letters[i/2] = secretCode[i];
        codes[i/2] = secretCode[i+1];
    }
    CodesCheck(message, letters, codes);
    System.out.println(Arrays.toString(gList.toArray()));
}
static void CodesCheck (String message, String[] letters, String[] codes) {
    for (int i = 0; i < codes.length; i++) {
        if (codes[i].length() <= message.length() && 
            codes[i].equals(message.substring(0, codes[i].length()))) {
            gList.add(letters[i]);
            String newMessage = message.substring(codes[i].length());
            if (newMessage.equals("")) {
                gList.add("|");
                return;
            }
            CodesCheck(newMessage, letters, codes);
        }
    }
}
}
公共类主{
静态列表gList=newarraylist();
公共静态void main(字符串[]args)引发IOException{
BufferedReader in=新的BufferedReader(新的InputStreamReader(System.in));
String message=in.readLine();/“1122”
字符串codeStr=in.readLine();/“A1B12C11D2”
//从代码中拆分字母:

String[]secretCode=codeStr.split(“[^A-Z0-9]+|”(?问题不在于函数,而在于输出:

如果您有多种可能性,您的程序将打印:

A [ output of recursive call with second letter A | ] [ output of recursive call with second letter B |].

相反,您应该做的是让每个调用返回结果glist(multiple),并且调用函数在它们的当前字母前面加上前缀。只有在最后,您才应该将|放在两者之间。

这是因为您的递归是这样工作的:

 * CodesCheck with "1122" and i=0 adds A, then calls itself with "122"
 ** CodesCheck with "122" and i=0 adds A, then calls itself with "22"
 *** CodesCheck with "22" and i=3 adds D, then calls itself with "2"
 **** CodesCheck with "2" and i=3 adds D, then adds | and returns because next message is ""
 *** CodesCheck with "22" returns because i > 3
 ** CodesCheck with "122" continues with i=1, adds B, then calls itself with "2"
 *** CodesCheck with "2" and i=3 adds D, then adds | and returns because next message is ""
 ** CodesCheck with "122" continues with i=2, finds nothing, continues with i=3, finds nothing, returns because i>3
 * CodesCheck with "1122" and i=1 finds nothing, continues with i=2, adds C, calls itself with "22"
 ** CodesCheck with "22" and i=3 adds D, then calls itself with "2"
 *** CodesCheck with "2" and i=3 adds D, then adds | and returns because next message is ""
 ** CodesCheck with "22" returns because i > 3
 * CodesCheck with "1122" continues with i=3, finds nothing, then returns because i > 3
要解决这个问题,您需要以某种方式跟踪递归调用,这意味着当处理
“122”
的方法继续执行
i=1
B
时,您需要知道之前有一个
A
,并且需要将其添加到
B
之前的列表中

一种方法是使用
堆栈

void CodesCheck (String message, String[] letters, String[] codes, Stack<String> stack) {

是的,这就是我最初的想法——使用列表列表,但我不确定如何实现它。堆栈在这里工作得很好,如果您在每个步骤中复制列表并在当前字符串之前添加前缀,它也会工作。堆栈的好处是它的性能更好,复制的好处是没有副作用(意味着不需要执行pop)。为了完整起见,使用HashMap(a->12等)和一组字符串固定代码以保留结果。以及适当的回溯:
CodesCheck(message, letters, codes, new Stack<String>());
stack.add(letters[i]);
final String newMessage = message.substring(codes[i].length());
if (newMessage.equals("")) {
    gList.addAll(stack);
    gList.add("|");
    stack.pop();
    return;
}
CodesCheck(newMessage, letters, codes, stack);
stack.pop();