Palindrome - tanakakenji/Rinko GitHub Wiki

C++でぎ回文īŧˆãƒ‘ãƒĒãƒŗãƒ‰ãƒ­ãƒŧムīŧ‰ãƒ†ã‚¯ãƒ‹ãƒƒã‚¯

回文とは、前からčĒ­ã‚“ã§ã‚‚åžŒã‚ã‹ã‚‰čĒ­ã‚“ã§ã‚‚åŒã˜ä¸ĻãŗãĢãĒる文字列ぎことです。ここでは、回文ãĢé–ĸする様々ãĒテクニックをC++ãŽã‚ŗãƒŧãƒ‰äž‹ã‚’į”¨ã„ãĻč§ŖčĒŦしぞす。

1. 文字列ぎ反čģĸãĢよる判厚

æœ€ã‚‚å˜į´”ãĒã‚ĸプロãƒŧチは、文字列を反čģĸさせãĻ元ぎ文字列と比čŧƒã™ã‚‹ã“とです。

#include <iostream>
#include <string>
#include <algorithm>

bool isPalindromeReverse(const std::string& s) {
    std::string reversed = s;
    std::reverse(reversed.begin(), reversed.end());
    return s == reversed;
}

int main() {
    std::string str = "racecar";
    std::cout << str << " is palindrome: " << (isPalindromeReverse(str) ? "Yes" : "No") << std::endl;
    return 0;
}

こぎã‚ĸプロãƒŧãƒã¯į°Ąå˜ã§ã™ãŒã€čŋŊåŠ ãŽãƒĄãƒĸãƒĒをäŊŋį”¨ã—ã€æ–‡å­—åˆ—å…¨äŊ“を反čģĸさせるåŋ…čĻãŒã‚ã‚Šãžã™ã€‚

2. 2ã¤ãŽãƒã‚¤ãƒŗã‚ŋをäŊŋį”¨ã—ãŸåˆ¤åŽš

ã‚ˆã‚ŠåŠšįŽ‡įš„ãĒã‚ĸプロãƒŧチは、2ã¤ãŽãƒã‚¤ãƒŗã‚ŋをäŊŋį”¨ã™ã‚‹ã“ã¨ã§ã™ã€‚

bool isPalindromeTwoPointers(const std::string& s) {
    int left = 0;
    int right = s.length() - 1;
    while (left < right) {
        if (s[left] != s[right]) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

こぎã‚ĸプロãƒŧチはčŋŊåŠ ãŽãƒĄãƒĸãƒĒをäŊŋį”¨ã›ãšã€åŋ…čρãĢåŋœã˜ãĻ旊期ãĢįĩ‚äē†ã§ããžã™ã€‚

3. 回文ぎ数を数える

å›žæ–‡ãŽæ•°ã‚’æ•°ãˆã‚‹å•éĄŒã§ã¯ã€ä¸­å¤Žã‹ã‚‰å¤–å´ãĢå‘ã‹ãŖãĻæ‹ĄåŧĩしãĻいくテクニックがよくäŊŋį”¨ã•ã‚Œãžã™ã€‚

int countPalindromes(const std::string& s) {
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        // åĨ‡æ•°é•ˇãŽå›žæ–‡
        count += expandAroundCenter(s, i, i);
        // åļæ•°é•ˇãŽå›žæ–‡
        count += expandAroundCenter(s, i, i + 1);
    }
    return count;
}

int expandAroundCenter(const std::string& s, int left, int right) {
    int count = 0;
    while (left >= 0 && right < s.length() && s[left] == s[right]) {
        count++;
        left--;
        right++;
    }
    return count;
}

こぎã‚ĸプロãƒŧチは、åĨ‡æ•°é•ˇã¨åļæ•°é•ˇãŽä¸Ąæ–šãŽå›žæ–‡ã‚’č€ƒæ…Žã—ãĻいぞす。

4. æœ€é•ˇå›žæ–‡éƒ¨åˆ†æ–‡å­—åˆ—

æœ€é•ˇå›žæ–‡éƒ¨åˆ†æ–‡å­—åˆ—ã‚’čĻ‹ã¤ã‘ã‚‹å•éĄŒã‚‚ã€ä¸­å¤Žã‹ã‚‰æ‹ĄåŧĩするテクニックをäŊŋį”¨ã—ãžã™ã€‚

std::string longestPalindromicSubstring(const std::string& s) {
    if (s.empty()) return "";
    int start = 0, maxLength = 1;
    for (int i = 0; i < s.length(); i++) {
        int len1 = expandAroundCenter(s, i, i);
        int len2 = expandAroundCenter(s, i, i + 1);
        int len = std::max(len1, len2);
        if (len > maxLength) {
            start = i - (len - 1) / 2;
            maxLength = len;
        }
    }
    return s.substr(start, maxLength);
}

int expandAroundCenter(const std::string& s, int left, int right) {
    while (left >= 0 && right < s.length() && s[left] == s[right]) {
        left--;
        right++;
    }
    return right - left - 1;
}

こぎã‚ĸプロãƒŧチは、各文字īŧˆåĨ‡æ•°é•ˇīŧ‰ã¨å„文字ペã‚ĸīŧˆåļæ•°é•ˇīŧ‰ã‚’中åŋƒã¨ã—ãĻæ‹Ąåŧĩã—ã€æœ€é•ˇãŽå›žæ–‡ã‚’čĻ‹ã¤ã‘ãžã™ã€‚

5. 回文部分列īŧˆå‹•įš„č¨ˆį”ģæŗ•īŧ‰

å›žæ–‡éƒ¨åˆ†åˆ—ãŽå•éĄŒã¯ã€é‡č¤‡ã™ã‚‹éƒ¨åˆ†å•éĄŒãŒã‚ã‚‹ãŸã‚ã€å‹•įš„č¨ˆį”ģæŗ•ã‚’äŊŋį”¨ã—ãžã™ã€‚

int longestPalindromicSubsequence(const std::string& s) {
    int n = s.length();
    std::vector<std::vector<int>> dp(n, std::vector<int>(n, 0));
    
    // すずãĻぎ1æ–‡å­—ã¯é•ˇã•1ぎ回文
    for (int i = 0; i < n; i++) {
        dp[i][i] = 1;
    }
    
    // é•ˇã•2äģĨ上ぎ部分列を埋める
    for (int len = 2; len <= n; len++) {
        for (int i = 0; i < n - len + 1; i++) {
            int j = i + len - 1;
            if (s[i] == s[j] && len == 2) {
                dp[i][j] = 2;
            }
            else if (s[i] == s[j]) {
                dp[i][j] = dp[i+1][j-1] + 2;
            }
            else {
                dp[i][j] = std::max(dp[i+1][j], dp[i][j-1]);
            }
        }
    }
    
    return dp[0][n-1];
}

ã“ãŽå‹•įš„č¨ˆį”ģæŗ•ぎã‚ĸプロãƒŧãƒã¯ã€éƒ¨åˆ†å•éĄŒãŽįĩæžœã‚’äŋå­˜ã—å†åˆŠį”¨ã™ã‚‹ã“ã¨ã§åŠšįŽ‡įš„ãĢč§Ŗã‚’æą‚ã‚ãžã™ã€‚

ぞとめ

  1. 文字列ぎ反čģĸ: į°Ąå˜ã ãŒčŋŊåŠ ãŽãƒĄãƒĸãƒĒをäŊŋᔍ
  2. 2ã¤ãŽãƒã‚¤ãƒŗã‚ŋ: åŠšįŽ‡įš„ã§čŋŊåŠ ãŽãƒĄãƒĸãƒĒをäŊŋį”¨ã—ãĒい
  3. 回文ぎ数を数える: ä¸­å¤Žã‹ã‚‰æ‹ĄåŧĩするテクニックをäŊŋᔍ
  4. æœ€é•ˇå›žæ–‡éƒ¨åˆ†æ–‡å­—åˆ—: ä¸­å¤Žã‹ã‚‰æ‹ĄåŧĩするテクニックをäŊŋᔍ
  5. 回文部分列: å‹•įš„č¨ˆį”ģæŗ•ã‚’äŊŋᔍ

これらぎテクニックを遊切ãĢé¸æŠžã—éŠį”¨ã™ã‚‹ã“ã¨ã§ã€æ§˜ã€…ãĒ回文é–ĸé€ŖãŽå•éĄŒã‚’åŠšįŽ‡įš„ãĢč§Ŗæąēã™ã‚‹ã“ã¨ãŒã§ããžã™ã€‚å•éĄŒãŽį‰šæ€§īŧˆéƒ¨åˆ†æ–‡å­—列 vs 部分列、ã‚Ģã‚Ļãƒŗãƒˆ vs æœ€é•ˇãĒおīŧ‰ãĢåŋœã˜ãĻ、最遊ãĒã‚ĸプロãƒŧチを選択することが重čĻã§ã™ã€‚

âš ī¸ **GitHub.com Fallback** âš ī¸