• Partitioning by Palindromes


    We say a sequence of characters is a palindrome if it is the same written forwards and backwards. For example, 'racecar' is a palindrome, but 'fastcar' is not.

    partition of a sequence of characters is a list of one or more disjoint non-empty groups of consecutive characters whose concatenation yields the initial sequence. For example, ('race', 'car') is a partition of 'racecar' into two groups.

    Given a sequence of characters, we can always create a partition of these characters such that each group in the partition is a palindrome! Given this observation it is natural to ask: what is the minimum number of groups needed for a given string such that every group is a palindrome?

    For example:

    • 'racecar' is already a palindrome, therefore it can be partitioned into one group.
    • 'fastcar' does not contain any non-trivial palindromes, so it must be partitioned as ('f', 'a', 's', 't', 'c', 'a', 'r').
    • 'aaadbccb' can be partitioned as ('aaa', 'd', 'bccb').

    Input begins with the number n of test cases. Each test case consists of a single line of between 1 and 1000 lowercase letters, with no whitespace within.

    For each test case, output a line containing the minimum number of groups required to partition the input into groups of palindromes.

    Sample Input

    3
    racecar
    fastcar
    aaadbccb
    

    Sample Output

    1
    7
    3

    题意:把字符串划分成尽量少的回文串。

    p[i]表示从i开始的最长回文字符串的长度
    dp[i]表示从i开始的最小回文串数目,dp[0]即为所求

           r  a c  e c a r
    p[]   7 5 3 1 1 1 1 1 (p[]的最后一位冗余)

    dp[] 1 2 3 4 3 2 1 0 (dp[]的最后一位是为了方便计算dp,模拟一下过程就知道了)

        f a  s t c  a r
    p[]   1 1 1 1 1 1 1 1

    dp[] 7 6 5 4 3 2 1 0

        a a a d b  c c b
    p[]   3 2 1 1 4 2 1 1 1

    dp[] 3 3 3 2 1 2 2 1 0

    dp[]从后往前刷,因为p[i]都是与它后面的元素相关联,所以应当先求后面的元素才能求前面的
    关于更新dp,对于每一位,可以把它当成一个回文字符串,或者把它当成一个更长的回文字符串(i to i+p[i]-1)
    所以 dp[i] = min(dp[i+p[i]]+1, dp[i+1]+1);

    #include <iostream>
    #include <string>
    using namespace std;
    
    string s;
    
    //从l到r是不是回文?
    bool palindromes(int l, int r)
    {
        for (int i = l, j = r; i < j; ++i,--j)
        {
            if (s[i] != s[j])
                return false;
        }
        
        return true;
    }
    
    int main()
    {
        int m;
        
        cin >> m;
        
        while (m--)
        {
            cin >> s;
            
            int size = s.size()+1;
            
            int p[size],dp[size];    //p[i]表示从i开始的最长回文字符串的长度 
                                    //dp[i]表示从i开始的最小回文串数目,dp[0]即为所求 
            for (int i = 0; i < size; ++i)
                p[i] = 1, dp[i] = 0; 
                
            for (int i = 0; i < s.size(); ++i)    //p[]从前往后刷
                for (int j = 1; i+j < s.size();++j)
                    if (palindromes(i, i+j))
                        p[i] = j+1;
            
            for (int i = size-2; i >= 0; --i)    //dp[]从后往前刷
                dp[i] = min(dp[i+p[i]]+1, dp[i+1]+1);
            
            cout << dp[0] << endl;
        }
    }
    View Code
  • 相关阅读:
    第一次极限测试效果图-完整四张
    第一次极限测试效果图
    ajax遍历list数据解决方法
    读书笔记1
    读书笔记2
    读书笔记3
    每日学习
    关于根据数据反选checkbox
    zabbix监控kernel.pid_max
    React 学习项目1
  • 原文地址:https://www.cnblogs.com/chenyg32/p/3135609.html
Copyright © 2020-2023  润新知