반응형

문제 출처 :


https://www.acmicpc.net/problem/1305



알고리즘 분석 :


문제 해결에 필요한 사항

1. 실패 함수


KMP 알고리즘의 실패 함수에 대해 알고 있으면 해결할 수 있는 문제이다.


실패 함수의 원리 자체가 접두사와 접미사가 얼마나 중첩되어있냐를 의미하는 것이고, 


그 원리를 이용하여 n - pi[n -1]이라는 방식을 이용하면 해결할 수 있게 된다.


좀더 자세한 내용은 다음과 같다.




조금만 생각해 보면 문자열 제곱 문제보다도 더 쉽습니다. 


답이 L보다 작으려면 문자열에 반복 구조가 있어야 하는데, 특히 문자열의 접미사와 접두사가 같은 경우가 생겨야 합니다.

예를 들면 "abcdab"는 "ab"가 양끝에서 반복되므로 "abcd"가 반복된다고 추론할 수 있습니다.

"abcabca"는 "a", "abca"가 양끝에서 반복되는데 정답은 작을수록 좋으므로 

반복되는 문자열은 "abcabc"보다는 "abc"를 취하게 됩니다.

그리고, 만약 fail[L-1]이 문자열 길이 절반보다 크다면? 

즉, "ababa"를 예로 보자면 "aba"가 최대로 반복되므로 fail[L-1] = 3입니다. 

때는 5-3 = 2가 정답이 되겠습니다.


이걸 보면 그냥 fail[L-1] 값에 달려있다는 걸 알 수 있죠. fail[L-1] = 0이면 답은 L이고, 아니면 답은 L - fail[L-1]이 됩니다.


출처 :: http://kks227.blog.me/220917078260





소스 코드 : 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
 
using namespace std;
 
vector<int> getPi(string p)
{
    int m = (int)p.size();
    int j = 0;
 
    vector<int> pi(m, 0);
 
    for (int i = 1; i< m; i++) {
        while (j > && p[i] != p[j])
            j = pi[j - 1];
        if (p[i] == p[j])
            pi[i] = ++j;
    }
    return pi;
}
 
int main()
{
    int n;
    char tmp[1000001];
    string p;
 
    scanf("%d"&n);
    scanf("%s", tmp);
 
    p = tmp;
 
    vector<int> pi = getPi(p);
    
    cout << n - pi[n - 1<< endl;
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[1167번] 트리의 지름  (4) 2017.02.23
[4354번] 문자열 제곱  (1) 2017.02.23
[11656번] 접미사 배열  (0) 2017.02.22
[1764번] 듣보잡  (0) 2017.02.20
[1068번] 트리  (0) 2017.02.20