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
  • 相关阅读:
    测试常用的sql语句总结
    测试常用的Linux命令总结
    【转载】vim 中如何替换选中行或指定几行内的文本
    1074 Reversing Linked List
    1077 Kuchiguse
    LC 355. Design Twitter
    LCP 5. 发 LeetCoin
    LC 1409. Queries on a Permutation With Key
    1095 Cars on Campus
    LC 1369. Get the Second Most Recent Activity
  • 原文地址:https://www.cnblogs.com/rainydays/p/3114060.html
Copyright © 2011-2022 走看看