HDU 2243

http://acm.split.hdu.edu.cn/showproblem.php?pid=2243

题意: 这题跟POJ 2778大体思路一样,只不过2778是找出不含有病毒串的,而这道题是找出含有病毒串的数量,那么我们只要找到不含病毒串的数量有多少个之后再用总数相减就好。但要记得这个题用的是邻接矩阵求出不满足的条件,之后再用矩阵存储
{26,1}
{0, 1} 这样的矩阵进行矩阵快速幂之后我们得到的a[0][1]这个值就是 26^1+26^2+26^3+…….+26^4…….得到的值之后减去不含病毒串的值就行

#include <cmath>
#include <queue>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL unsigned __int64
#define INF 0x3f3f3f3f
#define MME(i,j) memset(i,j,sizeof(i))
using namespace std;
const int maxn = 15;
const int mod = 1e5;
int m;char str[15];
int limted;
__int64 k;
struct matrix{LL a[111][111];}X;
matrix operator * (matrix a,matrix b)
{
    matrix c;
    MME(c.a,0);
    for(int i=0; i<limted; i++)
        for(int j=0; j<limted; j++) //实现矩阵乘法
        {
            for(int k=0; k<limted; k++)
            {
               c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]);
            }
        }

    return c;
}

matrix operator ^ (matrix a,LL b)
{
    matrix c;
    MME(c.a,0);
    for(long long i=0;i<limted;i++)
        c.a[i][i]=1;

    while(b)
    {
        if(b & 1) c= c * a ;
        b >>= 1;
        a = a * a ;
    }
    return c;
}
/*int ch(char c)
{
    if(c=='A') return 0;if(c=='C') return 1;
    if(c=='G') return 2;if(c=='T') return 3;
}*/
struct Trie
{
    int next[111][27],fail[111],end[111];
    int root,L;
    int newnode()
    {
        for(int i = 0;i < 26;i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L-1;
    }
    // init right********
    void init(){L = 0;root = newnode();}

    void insert(char buf[])
    {
        int id,len = strlen(buf);
        int now = root;

        for(int i = 0;i < len;i++)
        {
            id=buf[i]-'a';
            if(next[now][id] == -1)
                next[now][id] = newnode();
            now = next[now][id];
        }
        end[now]=1;
    }
    // insert right **************

    // build right  **************
    void build()
    {
        queue<int>Q;
        fail[root] = root;
        for(int i = 0;i < 26;i++)
            if(next[root][i] == -1)
                next[root][i] = root;
            else
            {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }

        while( !Q.empty() )
        {
            int now = Q.front();
            Q.pop();
            if(end[fail[now]])
                end[now]=1;
            for(int i = 0;i < 26;i++)
                if(next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }
}ac;


matrix getmatrix(matrix A)
{
    MME(A.a,0);

    for(int i=0;i<ac.L;i++)
        for(int j=0;j<26;j++)
            if( !ac.end[ac.next[i][j]] )
                A.a[i][ac.next[i][j]]++;
    //这里 不一样
    for(int i=0;i<=ac.L;i++)
        A.a[i][ac.L]=1;

    return A;
}

LL fun(LL x,LL n)
{
    LL res=1;
    while(n>0)
    {
        if(n & 1)
            res=(res*x);
        x=(x*x);
        n >>= 1;
    }
    return res;
}
int main()
{
    int i;
    while(~scanf("%d%I64d",&m,&k))
    {
        ac.init();
        for(i=1;i<=m;i++)
        {
            scanf("%s",str);
            ac.insert(str);
        }
        ac.build();

        limted=ac.L+1;
        X = getmatrix(X);
        X=X^k;
        //right
        // *******************

        LL ans = 0;
        for(i=0;i<=ac.L;i++) ans = (ans + X.a[0][i]);

        //这里 不懂
        X.a[0][0]=26;X.a[0][1]=X.a[1][1]=1;X.a[1][0]=0;
        limted=2;
        X=X^(k+1);//

        ans=X.a[0][1]-ans;

        printf("%I64u\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值