zoukankan      html  css  js  c++  java
  • HDU 4295 4 substrings problem

    HDU_4295

        可以用f[i][j][k]表示递推到S的第i个字符时,选取的字符串的集合为k(用二进制表示),从当前字符开始向后已经覆盖了长度j的字符。

        在这里不妨只讨论最小覆盖长度,最大覆盖长度类似。为了方便dp所以选用刷表的方式,首先令f[i][0][0]为0,接着对于任意一个f[i][j][k],实际上有两种决策,一种是当前这个位置什么也不放就过度到下一个字符,那么就有f[i+1][j-1][k]=std::min(f[i+1][j-1][k],f[i][j][k]),另一种就是从当前位置开始放上字符串t,这时要稍稍讨论一下,因为字符串t的长度可能会影响状态j,也就是从当前字符开始向后已经覆盖了的长度,设放上字符串t后的j的状态为nj,f的值nf,那么就有f[i][nj][k|1<<t]=std::min(f[i][nj][k|1<<t],nf)。

        为了能够方便的知道当前位置能否放上字符串t,就需要预处理出从S的各个位置开始是否能够放上a、b、c、d四个字符串,这里暴力也行KMP也行,反正这部分的复杂度对整体的复杂度来讲影响不大。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXL 4110
    #define INF 0x3f3f3f3f
    #define inf 0xc3c3c3c3
    char s[MAXL], b[4][70];
    int N, P[70], h[4][MAXL], len[4], f[MAXL][70][16];
    void KMP(int k)
    {
        int i, j;
        P[1] = 0;
        for(i = 2, j = 0; i <= len[k]; i ++)
        {
            while(j && b[k][j + 1] != b[k][i]) j = P[j];
            if(b[k][j + 1] == b[k][i]) ++ j;
            P[i] = j;
        }
        memset(h[k], 0, sizeof(h[k][0]) * (N + 1));
        for(i = 1, j = 0; i <= N; i ++)
        {
            while(j && b[k][j + 1] != s[i]) j = P[j];
            if(b[k][j + 1] == s[i]) ++ j;
            if(j == len[k]) h[k][i - len[k] + 1] = 1, j = P[j];
        }
    }
    void init()
    {
        int i, j, k;
        N = strlen(s + 1);
        for(i = 0; i < 4; i ++)
            scanf("%s", b[i] + 1), len[i] = strlen(b[i] + 1), KMP(i);
    }
    void dp(int c, const int &(&fun) (const int &, const int &))
    {
        int i, j, k, nj, nf, ans = c ? INF : inf;
        memset(f, c ? 0x3f : 0xc3, sizeof(f[0]) * (N + 1));
        for(i = 1; i <= N; i ++)
        {
            f[i][0][0] = 0;
            for(j = 0; j <= 64; j ++)
            {
                for(k = 0; k < 15; k ++)
                    if(f[i][j][k] != (c ? INF : inf))
                    {
                        int nj = j > 0 ? j - 1 : 0;
                        f[i + 1][nj][k] = fun(f[i + 1][nj][k], f[i][j][k]);
                        for(int t = 0; t < 4; t ++)
                            if((k & 1 << t) == 0 && h[t][i])
                            {
                                nj = std::max(j, len[t]);
                                f[i][nj][k | 1 << t] = fun(f[i][nj][k | 1 << t], f[i][j][k] + nj - j);
                            }
                    }
                ans = fun(ans, f[i][j][15]);
            }
        }
        printf("%d", ans);
    }
    void solve()
    {
        dp(1, std::min), printf(" "), dp(0, std::max), printf("\n");
    }
    int main()
    {
        while(scanf("%s", s + 1) == 1)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    003_&#x和ASCII的关系及URL中的中文转义
    001_机器学习的Hello world之MNIST手写数字识别模型
    Appnium安装-Mac平台
    Code Review 规范
    Spring AOP-xml配置
    JTLParser-linux上jmeter的jtl文件二次分析
    测试覆盖率Emma工具使用
    jmeter之java请求
    jmeter测试总结
    jstat监控gc情况
  • 原文地址:https://www.cnblogs.com/staginner/p/2691677.html
Copyright © 2011-2022 走看看