zoukankan      html  css  js  c++  java
  • poj1618

    题意:有n个长度为len的模式串,问在所有长度为L的串中有多少个串符合如下条件:该串所有长度为len的子串都在这n个模式串中。

    分析:动态规划,f[i][j]表示长度为i的以第j个模式串为后缀的符合条件的串有多少个,f[i + 1][k] += f[i][j];

    k要符合第k个模式串可以由第j个模式串去掉首字母,再在结尾添加一个字母得到。就相当于我们不断的将模式串有重叠地(重叠长度为len-1)搭在当前构成的长度为i的串的结尾,使长度变为i+1。

    也就是第k个模式串就是长度为i+1的串比长度为i的串多出的那个长度为len的子串(长度为i+1的串的长度为len的子串个数只比长度为i的串的长度为len的子串个数多1)。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    #define maxn 605
    #define maxl 30
    #define maxm 105
    
    struct Edge
    {
        int next, v;
    }edge[maxn * maxn];
    
    int head[maxn];
    int comb_cnt, type_cnt, streamer_len;
    int comb_len;
    char comb[maxn][maxl];
    int ecount;
    int f[maxm][maxn];
    
    void input()
    {
        for (int i = 0; i < comb_cnt; i++)
            scanf("%s", comb[i]);
    }
    
    void addedge(int a, int b)
    {
        edge[ecount].v = b;
        edge[ecount].next = head[a];
        head[a] = ecount++;
    }
    
    bool connect1(char *a, char *b)
    {
        for (int i = 1; i < comb_len; i++)
            if (a[i] != b[i - 1])
                return false;
        return true;
    }
    
    void make()
    {
        comb_len = strlen(comb[0]);
        ecount = 0;
        memset(head, -1, sizeof(head));
        for (int i = 0; i < comb_cnt; i++)
            for (int j = 0; j < comb_cnt; j++)
                if (connect1(comb[i], comb[j]))
                    addedge(i, j);
    }
    
    void work()
    {
        memset(f, 0, sizeof(f));
        for (int i = 0; i < comb_cnt; i++)
            f[comb_len][i] = 1;
        for (int i = comb_len; i < streamer_len; i++)
            for (int j = 0; j < comb_cnt; j++)
                for (int k = head[j]; k != -1; k = edge[k].next)
                    f[i + 1][edge[k].v] += f[i][j];
        int ans = 0;
        for (int i = 0; i < comb_cnt; i++)
            ans += f[streamer_len][i];
        printf("%d\n", ans);
    }
    
    int main()
    {
        while (scanf("%d%d%d", &type_cnt, &streamer_len, &comb_cnt), type_cnt | streamer_len | comb_cnt)
        {
            input();
            make();
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    hdu 6188 Duizi and Shunzi
    区间第k大
    AtCoder Regular Contest 081 E
    hdu 6170 Two strings
    hdu 6156 Palindrome Function
    2017百度之星初赛(B)-1006-小小粉丝度度熊 hdu 6119
    AtCoder Regular Contest 080 E
    hdu 6069 Counting Divisors
    hdu 6058 Kanade's sum (多校3)
    苹果曼和树
  • 原文地址:https://www.cnblogs.com/rainydays/p/3114060.html
Copyright © 2011-2022 走看看