zoukankan      html  css  js  c++  java
  • HDU 5677 ztr loves substring(Manacher+dp+二进制分解)

    题目链接:HDU 5677 ztr loves substring

    题意:有n个字符串,任选k个回文子串,问其长度之和能否等于L。

    题解:用manacher算法求出所有回文子串的长度,并记录各长度回文子串的个数,再用背包思想判断是否有解。

    dp[i][j]:选取i个回文子串,长度之和是否为j

    其中用到二进制分解思想,将回文串长为i的数量cnt[i]拆成1+2+4+8+…形式,进行优化。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 #define CLR(a,b) memset((a),(b),sizeof((a)))
     6 const int N = 105;
     7 int dp[N][N], w[N*N*N], cnt[N], cnt1[N*N*N];
     8 char s[N*2];
     9 void Manacher(char s[],int len) {
    10     char Ma[N*2];
    11     int Mp[N*2] , l = 0;
    12     CLR(Mp, 0);
    13     Ma[l++] = '$';  Ma[l++] = '#';
    14     for(int i = 0; i < len; i++) {
    15         Ma[l++] = s[i];  Ma[l++] = '#';
    16     }
    17     int mx = 0, id = 0;
    18     for(int i = 0;i < l; i++) {
    19         Mp[i] = mx > i ? min(Mp[2*id-i], mx-i) : 1;
    20         while(Ma[i+Mp[i]] == Ma[i-Mp[i]]) Mp[i]++;
    21         if(i + Mp[i] > mx) {
    22             id = i;
    23             mx = i + Mp[i];
    24         }
    25         if(Ma[i] == '#'&& Mp[i] == 1) continue;
    26         cnt[Mp[i]-1]++;//记录该回文串长度数量
    27     }
    28 }
    29 int main(){
    30     int t, i, j, n, k, l, x, num;
    31     scanf("%d", &t);
    32     while(t--) {
    33         scanf("%d%d%d", &n, &k, &l);
    34         CLR(dp, 0); CLR(cnt, 0);
    35         for(i = 0; i < n; ++i) {
    36             scanf("%s", s);
    37             int len = strlen(s);
    38             Manacher(s, len);
    39         }
    40         num = 0;
    41         for(i = 1; i <= 100; ++i) {
    42             for(j = 1; j <= cnt[i]; cnt[i] -= j, j <<= 1) {
    43                 w[num] = j * i;
    44                 cnt1[num++] = j;
    45             }
    46             if(cnt[i]) { w[num] = j * i; cnt1[num++] = j; }
    47         }
    48         dp[0][0] = 1;
    49         for(i = 0; i < num; ++i)
    50             for(j = l; j >= w[i]; --j)
    51                 for(x = cnt1[i]; x <= k; ++x)
    52                     dp[x][j] |= dp[x-cnt1[i]][j-w[i]];
    53         if(dp[k][l]) puts("True");
    54         else puts("False");
    55     }
    56     return 0;
    57 }
    0ms
  • 相关阅读:
    BZOJ 1036 [ZJOI2008]树的统计Count(动态树)
    HDU 4010 Query on The Trees(动态树)
    Bootstrap框架
    【价格谈判】——在生意场合胜出的50个谈判绝招
    导出
    邓_ Php·魔术方法
    邓_tp_笔记
    UI 网页三原色
    邓_ 表单验证
    邓_ ThinkPhp框架
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/6368786.html
Copyright © 2011-2022 走看看