Как перебрать большую строку с увеличением подстроки на 1 позицию? - PullRequest
1 голос
/ 01 февраля 2020

У меня есть строка с огромным числом (в тысячах символов):

String pi = "3.14159265358979323846264338327950288419716939937..."

Я хочу перебрать эту строку, захватывая 6 символов за раз и проверяя, соответствуют ли они заданному Строка:

String substring = "3.1415"

Однако на каждой последующей подстроке я хочу сдвинуть 1 позицию справа от символов в исходной строке:

substring = ".14159"
substring = "141592"
substring = "415926"
substring = "159265"

et c. et c.

Каков наилучший способ сделать это? Я рассмотрел методы StringBuilder, но преобразование в String каждая итерация может быть дорогостоящим. Строковый метод

substring(int beginIndex, int endIndex)

, кажется, подходит к тому, что я пытаюсь сделать, но я не знаю, можно ли увеличить эти индексы алгоритмически.

Ответы [ 3 ]

3 голосов
/ 01 февраля 2020

Я не знаю, можно ли алгоритмически увеличивать эти индексы.

Это параметры. Это значения, предоставленные вами для каждого вызова метода.

Вы можете указать все, что захотите, на основе переменных, констант, выражений, пользовательского ввода или чего-либо еще. В этом случае вы можете сохранить одну или две переменные, увеличить их и передать в качестве параметров.

Вот пример использования двух переменных, каждая из которых увеличивается на 1 на каждую итерацию:

class Main {
  public static void main(String[] args) {
    String pi = "3.14159265358979323846264338327950288419716939937...";
    for(int start=0, end=6; end <= pi.length(); start++, end++) {
      String substring = pi.substring(start, end);
      System.out.println(substring);
    }
  }
}
0 голосов
/ 01 февраля 2020

Или java 8 стиль

String pi = "3.14159265358979323846264338327950288419716939937...";
IntStream.range(0, pi.length() - 5)
        .mapToObj(i -> new StringBuffer(pi.substring(i, i + 6)))
        .forEach(System.out::println)
;

У вас есть возможность сделать это параллельно

String pi = "3.14159265358979323846264338327950288419716939937...";
IntStream.range(0, pi.length() - 5)
        .mapToObj(i -> new StringBuffer(pi.substring(i, i + 6)))
        .parallel()
        .forEach(System.out::println)
;    

Говоря о выступлениях classi c для l oop метод все еще немного быстрее; Вы должны сделать несколько тестов:

public class Main {

    static long firstTestTime;
    static long withStreamTime;

    static String pi = "3.141592653589793238462643383279502884197169399375105820974944592307816";

    public static void main(String[] args) {
        firstTest(pi);
        withStreams(pi);

        System.out.println("First Test: " + firstTestTime);
        System.out.println("With Streams: " + withStreamTime);
    }

    static void withStreams(String pi) {
        System.out.println("Starting stream test");
        long startTime = System.currentTimeMillis();

        IntStream.range(0, pi.length() - 5)
                .mapToObj(i -> new StringBuffer(pi.substring(i, i + 6)))
                //.parallel()
                .forEach(System.out::println)
        ;

        withStreamTime = System.currentTimeMillis() - startTime;
    }

    // By @that other guy
    static void firstTest(String pi) {
        System.out.println("Starting first test");
        long startTime = System.currentTimeMillis();

        for(int start=0, end=6; end <= pi.length(); start++, end++) {
            String substring = pi.substring(start, end);
            System.out.println(substring);
        }

        firstTestTime = System.currentTimeMillis() - startTime;
    }

}

Попробуйте увеличить длину греческого пи!

0 голосов
/ 01 февраля 2020

Вот алгоритм, который эффективен при сопоставлении значений. Может быть более эффективным, чем использование методов подстроки, так как он замыкается, как только значения не соответствуют предоставленной последовательности.

public static int containsSubstring(String wholeString, String findValue) {
    //Break values into arrays
    char[] wholeArray = wholeString.toCharArray();
    char[] findArray = findValue.toCharArray();

    //Use named outer loop for easy continuation to next character place
    outerLoop:
    for(int i = 0; i < wholeArray.length; i++) {
        //Remaining values aren't large enough to contain find values so stop looking
        if(i + findArray.length > wholeArray.length) {
            break;
        }

        //Loop through next couple digits to check for matching sequence
        for(int j = 0; j < findArray.length; j++) {
            //Breaks loop as soon as a values don't match
            if(wholeArray[i + j] != findArray[j]) {
                continue outerLoop;
            }
        }

        return i; //Or 'true' of you just care whether it's in there, and set the method return to boolean
    }

    return -1; //Or 'false'
}
...