647. Palindromic Substrings 516. Longest Palindromic Subsequence

647. Palindromic Substrings

Given a string s, return the number of palindromic substrings 回文子串 in it.

A string is a palindrome when it reads the same backward as forward.

substring is a contiguous sequence of characters within the string.

nomal:

Time complexity: O(n^2)
Space complexity: O(1)

class Solution:
    def countSubstrings(self, s: str) -> int:
        count = 0

        for left in range(len(s)):
            for right in range(left, len(s)):
                if s[left : right + 1] == s[left : right + 1][::-1]: # wrong:[-1]最后一个字符
                    count += 1
        return count

DP:

Time complexity: O(n^2)
Space complexity: O(n^2)

class Solution:
    def countSubstrings(self, s: str) -> int:
        dp = [[False] * len(s) for _ in range(len(s))]
        result = 0
        for i in range(len(s)-1, -1, -1): #注意遍历顺序
            for j in range(i, len(s)):
                if s[i] == s[j]:
                    if j - i <= 1: #情况一 和 情况二
                        result += 1
                        dp[i][j] = True
                    elif dp[i+1][j-1]: #情况三
                        result += 1
                        dp[i][j] = True
        return result

 2 pointer:

Determining the palindrome string is a matter of finding the center and then spreading it out to both sides to see if it is symmetrical.

When traversing the central point, it is important to note that there are two cases of central points.

One element can be used as the center point, and two elements can be used as the center point.

Time complexity: O(n^2)
Space complexity: O(1)

class Solution:
    def countSubstrings(self, s: str) -> int:
        result = 0
        for i in range(len(s)):
            result += self.extend(s, i, i, len(s)) #以i为中心
            result += self.extend(s, i, i+1, len(s)) #以i和i+1为中心
        return result
    
    def extend(self, s, i, j, n):
        res = 0
        while i >= 0 and j < n and s[i] == s[j]:
            i -= 1
            j += 1
            res += 1
        return res

516. Longest Palindromic Subsequence

Given a string s, find the longest palindromic subsequence回文子序列's length in s.

subsequence is a sequence that can be derived衍生 from another sequence by deleting some or no elements without changing the order of the remaining elements.

1. dp[i][j]: the length of the longest palindrome subsequence of the string s in the range [i, j] is                        dp[i][j].

2. If s[i] is the same as s[j]: then dp[i][j] = dp[i + 1][j - 1] + 2;

3. If s[i] is not the same as s[j]: then dp[i][j] must be taken to be maximal,

                        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​     dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

 4. Determine the traversal order

5. initial 

    for i in range(len(s)):

              dp[i][i] == 1

6. return

DP: 

Time complexity: O(n^2)
Space complexity: O(n^2)

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        dp = [[0] * len(s) for _ in range(len(s))]
        for i in range(len(s)):
            dp[i][i] = 1
        for i in range(len(s)-1, -1, -1):
            for j in range(i+1, len(s)):
                if s[i] == s[j]:
                    dp[i][j] = dp[i+1][j-1] + 2
                else:
                    dp[i][j] = max(dp[i+1][j], dp[i][j-1])
        return dp[0][-1]

dfs:

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        n = len(s)

        # 使用记忆化搜索实现
        @cache
        def dfs(i, j):
            if i > j:
                return 0
            if i == j:
                return 1
            if s[i] == s[j]:
                return dfs(i + 1, j - 1) + 2
            else:
                return max(dfs(i + 1, j), dfs(i, j - 1))
        return dfs(0, n - 1)

回文树(Palindrome Tree),也称为字典树或自动机树,是一种用于高效查找字符串中所有子串是否为回文的方法的数据结构。在C++中,我们可以使用前缀树(Trie)为基础,对每个节点添加一个标记,表示其后缀是否为回文。 以下是一个简单的回文树实现步骤: 1. **定义节点**: 创建一个`Node`类,包含一个字符数组`children`用于存储子节点、一个布尔值`is_palindrome`标记当前节点及其所有后缀是否为回文,以及一个指向父节点的指针。 ```cpp class Node { public: char c; bool is_palindrome; Node* children[26]; // 26 for ASCII alphabet, adjust if needed Node(Node* parent); }; ``` 2. **构造函数**: 初始化字符和指向父节点的指针。 ```cpp Node::Node(Node* parent) : parent(parent), c('\0'), is_palindrome(false) { for (int i = 0; i < 26; ++i) children[i] = nullptr; } ``` 3. **插入操作**: 插入单词时,从根节点开始遍历,如果遇到某个字符不存在于子节点中,则新建一个子节点。同时,检查新插入的子串是否为回文。 ```cpp void insert(Node*& root, const string& word) { Node* node = &root; for (char c : word) { int idx = c - 'a'; // 根据ASCII调整 if (!node->children[idx]) { node->children[idx] = new Node(node); } node = node->children[idx]; if (word.size() > 1 && word[word.size() - 1] == c) { // 遍历过程中检查末尾是否成对出现 node->is_palindrome = true; } } } ``` 4. **查询操作**: 检查给定的子串是否在树中并返回所有回文后缀。 ```cpp vector<string> findPalindromes(Node* root, const string& prefix) { vector<string> result; dfs(root, prefix, result); return result; } void dfs(Node* node, const string& prefix, vector<string>& result) { if (!node) return; if (node->is_palindrome && !prefix.empty()) { result.push_back(prefix); } for (int i = 0; i < 26; ++i) { if (node->children[i]) dfs(node->children[i], prefix + node->c, result); } } ``` 5. **构建回文树**: 对输入的一系列单词进行插入,构建完整个树。 ```cpp Node* buildPalindromeTree(const vector<string>& words) { Node* root = new Node(nullptr); for (const auto& word : words) { insert(root, word); } return root; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值