본문 바로가기
알고리즘 문제풀이/leetcode

[leetcode 647] Palindromic Substrings

by m2162003 2020. 10. 6.

palindromic substring을 세는 문제

 

Example 1:

Input: "abc" Output: 3

Explanation: Three palindromic strings: "a", "b", "c".

 

Example 2:

Input: "aaa" Output: 6

Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

 

Note:

  1. The input string length won't exceed 1000.

다행히 문자열이 1000을 안넘어서 그런지 for문 돌려도 통과했다...하지만 몹시 느린 것이 사실

class Solution {
public:
    int countSubstrings(string s) {
        int result = 0;
        if(s.length() == 0){
            return result;
        }
        result += s.length();
        
        for(int i=0;i<s.length();i++){
            //i is the length of substring
            for(int j=i+1; j<s.length(); j++){
                int start = i;
                int end = j;
                bool flag = true;
                
                if(s[start] == s[end]){
                    while(start<end){
                        
                        if(s[start]!=s[end]){
                            flag = false;
                            break;
                        }
                        start++;
                        end--;
                    }
                    
                    if(flag == true){
                        cout<<i<<" "<<j<<"\n";
                        result++;
                    }
                }
            }
        }
        return result;
    }
};

 

좀 더 빠른 방법을 알아보자 - 다른 사람 풀이 참고

위에서 쓴 방법은 string의 각 idx i에 j만큼의 길이인 palindromic substring이 존재하는지 체크하는 구조이다.

i                                             j

  i+1 i +2  ....

                       .....     j-2  j-1

 

 

방법을 바꿔서 가운데 만나는 지점을 시작점으로 해보자

서브스트링의 길이가 홀수인 경우 i에서 출발한다.

짝수인 경우 i와 i+1에서 출발한다. 두 지점중 하나라도 조건을 벗어난다면 while문을 빠져나온다.

class Solution {
public:
    int countSubstrings(string s) {
        int L = s.length();
        
        int res = 0;
        for(int i=0; i<L; i++){
            int j=i, k=i;
            while(j>=0 && k<L && s[j] == s[k]){
                res++;
                j--;
                k++;
            }
            
            j=i; k=i+1;
            while(j>=0 && k<L && s[j] == s[k]){
                res++;
                j--;
                k++;
            }
        }
        
        return res;
    }
};

 

 

사실 이 문제는 dp로 표기되어 있다. dp로 푼 풀이도 살펴보자.

dp를 이차원 배열로 선언: dp[i][j]는 index가 i부터 j까지 인 서브스트링이 palindromic한지 true/false를 저장한다.서브스트링의 길이가 1인 경우, 즉 i=j인 경우 모두 true이다.

 

서브스트링의 길이가 3이상인 경우i가 start idx, j가 end idx라고 두고if (dp[i+1][j-1] = true && s[i] == s[j]) then dp[i][j] = true 의 식을 도출할 수 있다.

 

int countSubstrings(String s) {
    if (s.length() == 0) {
        return 0;
    }
    
    int n = s.length();
    // dp[i][j] will be false if substring str[i..j]
    // is not palindrome. Else, dp[i][j] will be true
    bool dp[n][n];

    int count = 0;

    // 길이가 1인 경우 전부 palindrome
    for (int i = 0; i < n; i++) {
        dp[i][i] = true;
        count++;
    }

    int i, ls, j;

    //substring 길이가 2일 때
    for (i = 0; i < n - 1; i++) {
        if (s[i] == s[i + 1]) {
            dp[i][i + 1] = true;
            count++;
        }
    }

    // Check for lengths greater than 2
    // ls는 substring 길이
    for (ls = 3; ls <= n; ls++) {
        // i is the starting index
        for (i = 0; i < n - ls + 1; i++) {
            // j is ending index of substring from starting index i and length ls
            j = i + ls - 1;
           
            if (dp[i + 1][j - 1] && s[i] == s[j]) {
                dp[i][j] = true;
                count++;
            }
        }
    }

    return count;
}

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

[leetcode 416] Partition Equal Subset Sum  (0) 2020.10.06
[leetcode 494] Target Sum  (0) 2020.10.06
[leetcode 739] Daily Temperatures  (0) 2020.10.05
[leetcode 621] Task Scheduler  (0) 2020.10.05
[leetcode 71] Simplify Path  (0) 2020.10.05

댓글