zoukankan      html  css  js  c++  java
  • Scau 8633 回文划分 mancher + dp

    时间限制:1000MS  内存限制:1000K
    提交次数:169 通过次数:63
    
    题型: 编程题   语言: G++;GCC
    
     
    
    Description
    
        我们说一个字符串是回文串,那么意味着这个串从两边读起来的字母都是一样的。例如racecar是回文串,
    然而fastcar则不是。
        对一个串的划分意思是将一个串划分为若干个部分。例如,racecar可以划分为race 和car两部分。给出
    一个串,要把这个串划分为若干个回文串,那么至少要把这个串划分为多少部分?
    例如
    'racecar'已经是回文串,划分为1 个部分即可(这个部分就是racecar)。
    'fastcar' 需要被划分为七个部分 ('f', 'a', 's', 't', 'c', 'a', 'r')。根据回文串的定义,单个字母也是回文串。
    'aaadbccb' 分成可以被分为三个回文串 ('aaa', 'd', 'bccb')。找不到更少的划分方法。
    
    
    
    
    输入格式
    
    输入的第一行是数字T,表示输入文件含有T个CASE。之后有T行,每行有一个长度不大于1000的字
    符串,全部由小写字母组成,中间没有空格。
    
    
    
    输出格式
    
    对于每个CASE,输出一个数字,表示对该字符串的回文串最小划分。
    
    
    
     
    
    输入样例
    
    3
    racecar
    fastcar
    aaadbccb
    
    
    
     
    
    输出样例
    
    1
    7
    3
    
    
    
     
    
    提示
    
    
    
    
     
    
    来源
    
     PKKJ @ 07 GIS 1 
    
     
    
    dp[i]表示前i个字符最少能被划分为回文串的个数
    
    转移就很简单了:dp[i] = min(dp[j - 1]) + 1; 其中 1 <= j <= i 并且 (s[j]~s[i])是回文串
    
    直接算复杂度是O(n^3),显然不行,可以用mancher预处理出vis[i][j], 表示(s[i]~s[j])是否是回文串
    
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N = 1005;
    char s[N], str[N << 1];
    bool vis[N][N];
    int dp[N], p[N << 1], len;
    void get(int n)
    {
        int mx = 0, id = 0;
        for(int i = 0; i < n; ++i)
        {
            p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
            while(str[i + p[i]] == str[i - p[i]]) p[i]++;
            if(i + p[i] > mx) {
                mx = i + p[i];
                id = i;
            }
        }
    }
    void pre(int n)
    {
        memset(vis, false, sizeof vis);
        for(int i = 2; i < n; ++i)
        {
            if(i & 1) {
                int st = i - 1;
                int ed = i + 1;
                int to = i - p[i] + 1;
                while(st >= to) { vis[st >> 1][ed >> 1] = true; st -= 2; ed += 2; }
            }else {
                int id = i >> 1;
                vis[id][id] = true;
                int st = i - 2;
                int ed = i + 2;
                int to = i - p[i] + 1;
                while(st >= to) { vis[st >> 1][ed >> 1] = true; st -= 2; ed += 2; }
            }
        }
    }
    void init()
    {
        int n = 0;
        str[n++] = '$';
        str[n++] = '#';
        for(int i = 0; i < len; ++i) {
            str[n++] = s[i];
            str[n++] = '#';
        }
        str[n] = 0;
        get(n);
        pre(n);
    
    }
    void solve()
    {
        dp[0] = 0;
        for(int i = 1; i <= len; ++i)
        {
            dp[i] = 0x3f3f3f3f;
            for(int j = 1; j <= i; ++j) if(vis[j][i])
                dp[i] = min(dp[i], dp[j - 1] + 1);
        }
        printf("%d
    ", dp[len]);
    }
    int main()
    {
        int _; scanf("%d", &_);
        while(_ --)
        {
            scanf("%s", s);
            len = strlen(s);
            init();
            solve();
        }
        return 0;
    }
      
  • 相关阅读:
    centos7 常用工具包安装
    Java.lang.String类
    javaweb系统调优方案
    nginx 优化
    centos7 源码安装nginx
    tomcat8调优
    commons-logging slf4j log4j 区别
    docker 安装centos7并SSH远程连接
    aws mysql 开启慢查询日志, 并利用mysqlsla 分析
    centos7 源码安装goaccess
  • 原文地址:https://www.cnblogs.com/orchidzjl/p/4912611.html
Copyright © 2011-2022 走看看