publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); br.readLine();
int answer = solution(n, br.readLine());
System.out.println(answer); }
publicstaticintsolution(int n, String target){ int answer = 0;
m이 패턴의 길이보다 작고, 문자열 s(OOIOIIOIOIOIOIOIOIOIOOIOI) 에서 start+m 한 index의 문자와 비교할 패턴(IOIOI)의 m 번째 문자가 같지 않으므로 s에서 비교가 시작되는 위치를 1 증가 시킨다. (현재 start = 1, m = 0)
S의 1와 패턴의 0을 비교해도 여전히 같지 않으므로 시작 위치를 또 증가 시킨다. (start = 2, m = 0)
S의 2와 패턴의 0을 비교하면 둘다 ‘I’로 같으므로 m을 증가 시키고 패턴의 길이와 같을 때 까지 반복한다. (start = 2, m = 1)
S의 3와 패턴의 1을 비교하면 둘다 ‘O’로 같으므로 m을 증가 시키고 패턴의 길이와 같을 때 까지 반복한다. (start = 2, m = 2)
S의 4와 패턴의 2을 비교하면 둘다 ‘I’로 같으므로 m을 증가 시키고 패턴의 길이와 같을 때 까지 반복한다. (start = 2, m = 3)
S의 5와 패턴의 3을 비교하면 같지 않고 이제 m이 0이 아니므로,
s의 시작 위치를 증가 시켜야 하는데 1을 증가 시키는게 아니라 이전에 구한 실패 함수 값에서 찾아온다.
(m(3) - 실패함수 값 array[m(3) - 1]) = 2
즉 현재 시작 위치에서 1을 더한 값이 아닌 2를 더한다.
이미 index 4까지는 접두사 접미사가 2 자리까지 같기 때문에
m 역시 실패함수 값을 가져온다.
IOIOI에서 IOIO까지 비교한 값에서 실패했기 떄문에
그 이전 접미사 접두사 길이만큼으로 비교한다.
이 시점에서 start = 4, m = 1이 되고 루프를 반복한다.
4와 1은 같지 않으므로 다시 7번부터 8번까지 반복해서 start와 m을 조정한다.
이 예제로 하면 처음부터 같지 않았으므로 start는 한칸만 뒤로 가고
m 역시 접두사 접미사 1 짜리도 실패했으므로 처음부터 비교한다.
(start = 5, m = 0)
(5, 0), (6, 1), (7, 2), (8, 3), (9, 4) 이 쭉~ 같으므로 드디어 문자열 s에서 패턴을 찾은 것이므로 answer을 증가 시킨다.
그 이후로 다시 비교하면 m의 길이가 패턴의 길이를 넘어 갔으므로,
start와 m의 위치를 다시 조정한다.
반복
끝.
결국 정리하면, 처음 말한 것 처럼 이미 비교한 값은 다시 비교하지 않고 그 다음 부터 비교하는 방식으로 시간을 줄인다.
더 자세한 설명들은 글 마지막 참고 사이트를 찾아가면 다른 분들이 매우 자세하게 설명해주시고 계신다.