HDU2243-----AC自动机+矩阵乘法+矩阵公式

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2243

题目意思:

给你n个字符串,然后给你一个长度L

问你在长度不超过L的所有字符串中(a~z)有多少个至少含有一个子串


意思很明确了,下面说解法,这题和POJ2778很类似,详见:http://blog.csdn.net/dr5459/article/details/8971626

那我们就建立一个自动机,通过和POJ2778类似的方式把跳转矩阵A求出来

然后求A^1+A^2+A^3+A^4+...+A^L求出来

但是这个太麻烦了,我们要引入一个公式:

HDU2243-----AC自动机+矩阵乘法+矩阵公式_第1张图片

通过这个方法就可以求出某个矩阵的连续指数和,然后减去E就可以了

那么我们就可以求L+1次方就可以,因为我们最后只是求的是矩阵的第一列,所以在答案中-1就行

那么这是不可能的,我们在求出26^1+26^2+...+26^n就可以了

一相减即为结果。因为要模2^64次方,我们用unsigned long long就可以

另外杭电上要用%I64u,不然会有各种错误。

代码:

#include
#include
#include
#include
#include
using namespace std;

#define ULL unsigned long long

const int maxnode = 6*6+5;
const int size=26;

struct AC
{
    int ch[maxnode][size];
    int f[maxnode];
    bool val[maxnode];
    int sz;

    void init()
    {
        memset(ch[0],-1,sizeof(ch[0]));
        sz=1;
        val[0]=false;
    }

    int idx(char c)
    {
        return c-'a';
    }

    void insert(char *s)
    {
        int len = strlen(s);
        int u=0;
        for(int i=0;i q;
        for(int i=0;i=n && i==j)
                tmp.m[i][j] = 1;
        }
    }
    maxtrixpower(l+1,tmp,tmp,ac.sz*2);
    ULL ans=0;
    for(int i=n;i<2*n;i++)
        ans+=tmp.m[0][i];
    return ans-1;
}


int main()
{
    ULL m,l;
    while(~scanf("%I64u%I64u",&m,&l))
    {
        ac.init();
        char op[10];
        for(int i=0;i


你可能感兴趣的:(数学,矩阵系列,数据结构)