zoukankan      html  css  js  c++  java
  • LightOJ 1044 Palindrome Partitioning(简单字符串DP)

    A palindrome partition is the partitioning of a string such that each separate substring is a palindrome.

    For example, the string "ABACABA" could be partitioned in several different ways, such as {"A","B","A","C","A","B","A"}, {"A","BACAB","A"}, {"ABA","C","ABA"}, or {"ABACABA"}, among others.

    You are given a string s. Return the minimum possible number of substrings in a palindrome partition of s.

    Input

    Input starts with an integer T (≤ 40), denoting the number of test cases.

    Each case begins with a non-empty string s of uppercase letters with length no more than 1000.

    Output

    For each case of input you have to print the case number and the desired result.

    Sample Input

    3

    AAAA

    ABCDEFGH

    QWERTYTREWQWERT

    Sample Output

    Case 1: 1

    Case 2: 8

    Case 3: 5

    题意:给出一个字符串,将该字符串切割成若干个回文串,使切割后的回文串数最小,求这个回文串数

    题解:这道题其实在之前DP百题大过关中已经出现过了,复杂度是n^3的,今天写的时候突然糊出了n^2的做法,再记录一下

    首先是状态转移方程的推导

    f[i]表示1-i之间的最小分割数,很显然只有当i~j是回文串的时候i-1才能转移到j,贡献为1

    所以状态转移方程为

    f[j]=max{f[i-1]+1}(i~j为回文串)

    这个转移方程是n^2的,但上次写的时候在里面加入了O(N)的回文串判断,复杂度变成了O(N^3)

    如今想想,其实是不是回文串这东西是可以预处理的

    枚举每一个中点,向两边拓展,可以在O(N^2)中处理出每一段i~j是否是回文串

    然后就有了O(N^2)复杂度的DP

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    int c[1010][1010],n,f[1010];
    char s[1010];
    
    void get(int l,int r)
    {
        while(l>0&&r<=n)
        {
            if(s[l]==s[r])
            {
                c[l][r]=1;
            }
            else
            {
                return ;
            }
            l--;
            r++;
        }
    }
    
    int main()
    {
        int t,ttt=0;
        scanf("%d",&t);
        while(t--)
        {
            ttt++;
            memset(f,0x3f,sizeof(f));
            memset(c,0,sizeof(c));
            scanf("%s",s+1);
            n=strlen(s+1);
            for(int i=1; i<=n; i++)
            {
                get(i,i);
                get(i,i+1);
            }
            f[0]=0;
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=i; j++)
                {
                    if(c[j][i])
                    {
                        f[i]=min(f[i],f[j-1]+1);
                    }
                }
            }
            printf("Case %d: %d
    ",ttt,f[n]);
        }
    
    }

    大佬们的常数都好优越啊,N^3跑的都比N^2快qwq

  • 相关阅读:
    Python之路【第十六篇】:Django【基础篇】
    pyCharm最新2018激活码
    python selenium firefox使用
    IO编程(2)-操作文件和目录
    IO编程(1)-文件读写
    错误、调试和测试(4)-文档测试
    错误、调试和测试(3)-单元测试
    错误、调试和测试(2)-调试
    错误、调试和测试(1)-错误处理
    面向对象高级编程(5)-使用元类
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9280830.html
Copyright © 2011-2022 走看看