• UVa 11584 Partitioning by Palindromes 回文串dp


    Problem H: Partitioning by Palindromes

    Can you read upside-down?

    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
    

    ------------------------

    我又智硬了吗orz

    f[i]=min(f[j-1]+1) ( j<i,rev[j,i])

    -----------------------

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int OO=1e9;
    int n;
    char s[1111];
    int f[1111];
    bool rev[1111][1111];
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            memset(rev,0,sizeof(rev));
            scanf("%s",s+1);
            n=strlen(s+1);
            for (int i=1;i<=n;i++)
            {
                rev[i][i]=true;
                if (s[i]==s[i+1]&&i+1<=n)
                {
                    rev[i][i+1]=true;
                }
            }
            for (int k=2;k<=n;k++)
            {
                for (int i=1;i+k<=n;i++)
                {
                    if (s[i]==s[i+k]&&rev[i+1][i+k-1])
                    {
                        rev[i][i+k]=true;
                    }
                }
            }
            for (int i=1;i<=n;i++) f[i]=OO;
            f[0]=0;
            for (int i=1;i<=n;i++)
            {
                for (int j=1;j<=i;j++)
                {
                    if (rev[j][i])
                    {
                        f[i]=min(f[i],f[j-1]+1);
                    }
                }
            }
            int ans=f[n];
            printf("%d\n",ans);
        }
        return 0;
    }







  • 相关阅读:
    [HAOI2015]按位或
    CF451E Devu and Flowers
    [APIO2017]商旅
    后缀自动机总结
    [HNOI2011]括号修复 / [JSOI2011]括号序列
    [WC2021] 括号路径
    批处理系列(3)
    SQL关于子集中有NULL的问题解析
    SQL排除满足同时多个条件的记录行
    SQLServer 通过导入数据的形式复制数据库
  • 原文地址:https://www.cnblogs.com/cyendra/p/3226343.html
Copyright © 2020-2023  润新知