POJ 1625 Censored!(AC自动机+DP)

POJ 1625 Censored!(AC自动机+DP)

http://poj.org/problem?id=1625

题意:

        给你由特定N个字符组成的P个模板和长度M,问你由这特定N个字符组成的长为M的文本串不包含任意一个模板有多少种情况?M<=50

分析:

        由于M<=50,所以直接用DP做,不用矩阵幂算.本题很类似UVA11468:

http://blog.csdn.net/u013480600/article/details/23294375

        我们令d[i][j]=x表示当前在i号节点,还有j步要走且不经过后缀单词节点的情况总数为x.

        初值d[i][0]=1. i为非单词节点

        d[i][j] = sum(d[k][j-1])其中从i可以走到k,且i和k节点都不是后缀单词节点.

        最后我们所求为d[0][m]。(用本解法可以使用记忆话搜索,因为我们很容易知道d[i][j]的所有依赖项d[k][j-1])

        或者可以这么推(程序中用的就是该方式):

        令d[i][j]=x表示当前在i点,已经走过了j距离的情况总数为x.

        d[i][j]=sum(d[k][j-1])从k可以走到i,且k和i都是非单词节点.

        初值为d[0][0]=1.其他都为0,然后用滚动数组递推即可。(用本节点只能使用递推刷新求DP,因为我们无法知道d[i][j]的所有依赖项d[k][j-1])

AC代码:1A

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxnode=100+20;
int sigma_size;//后面读入
struct AC_Automata
{
    int ch[maxnode][50+20];
    int match[maxnode];
    int f[maxnode];
    map mp;
    int sz;
    void init()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        match[0]=f[0]=0;
        mp.clear();
    }
    void insert(char *s)
    {
        int n=strlen(s),u=0;
        for(int i=0;i q;
        for(int i=0;i=1;i--)
            if(ans[i])
            break;
        for(;i>=0;i--)
            printf("%d",ans[i]);
        putchar('\n');
    }
    return 0;
}


你可能感兴趣的:(ACM--题解汇总,注意!,数据结构--AC自动机,practice,again,★★★)