zoukankan      html  css  js  c++  java
  • hdu-2243(AC自动机+矩阵快速幂)

    题意:给你n个字符串,和长度m,问你长度<=m的字符串中,包括这n个字符串的有多少个

    解题思路:这题和poj2778差不多,但是那道题求的是不包含的,所有我们换个角度,求出所有的可能性减去不包括的就是了,但这道题有一个和那道题不一样的地方就是,他是<=长度len的所有,所有需要构造矩阵的时候加一列全为1的元素,然后求所有可能性也需要这样,构造一个2x2的矩阵【26 1 0 1】的矩阵,因为是对2^64取模,所以直接开unsigned long long 就行了

    代码

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue>
    using namespace std;
    typedef unsigned long long ll;
    const int N=50;
    const int maxn=110;
    ll m;
    int tot,n,cnt;
    int fail[N];
    int trie[N][26];
    int visit[N];
    char t[10];
    struct Matrix
    {
        ll m[maxn][maxn];
        Matrix()
        {
            memset(m,0,sizeof(m));
        }
        void init()
        {
            for(int i=0; i<=cnt; i++)
                for(int j=0; j<=cnt; j++)
                    m[i][j]=(i==j);
        }
        Matrix  operator +(const Matrix &b)const
        {
            Matrix c;
            for(int i=0; i<=cnt; i++)
            {
                for(int j=0; j<=cnt; j++)
                {
                    c.m[i][j]=(m[i][j]+b.m[i][j]);
                }
            }
            return c;
        }
        Matrix  operator *(const Matrix &b)const
        {
            Matrix c;
            for(int i=0; i<=cnt; i++)
            {
                for(int j=0; j<=cnt; j++)
                {
                    for(int k=0; k<=cnt; k++)
                    {
                        c.m[i][j]=(c.m[i][j]+(m[i][k]*b.m[k][j]));
                    }
                }
            }
            return c;
        }
        Matrix  operator^(const ll &t)const
        {
            Matrix ans,a=(*this);
            ans.init();
            ll n=t;
            while(n)
            {
                if(n&1) ans=ans*a;
                a=a*a;
                n>>=1;
            }
            return ans;
        }
    };
    void build_trie(char *str)
    {
        int root=0;
        int slen=strlen(str);
        for(int i=0;i<slen;i++)
        {
            int id=str[i]-'a';
            if(!trie[root][id])
                trie[root][id]=++tot;
            root=trie[root][id];
        }
        visit[root]=1;
    }
    void build_fail()
    {
        queue<int>q;
        for(int i=0;i<26;i++)
            if(trie[0][i]!=0)
                q.push(trie[0][i]);
        while(!q.empty())
        {
            int now=q.front();q.pop();
            if(visit[fail[now]])
                visit[now]=1;
            for(int i=0;i<26;i++)
            {
                if(!trie[now][i])
                {
                    trie[now][i]=trie[fail[now]][i];
                    continue;
                }
                fail[trie[now][i]]=trie[fail[now]][i];
                q.push(trie[now][i]);
            }
        }
    }
    void init()
    {
        memset(trie,0,sizeof(trie));
        memset(fail,0,sizeof(fail));
        memset(visit,0,sizeof(visit));
        tot=0;
    }
    int main()
    {
        while(scanf("%d%u",&n,&m)!=EOF)
        {
            Matrix a,b;init();
            for(int i=1;i<=n;i++)
            {
                scanf("%s",t);build_trie(t);
            }
            build_fail();
            for(int i=0;i<=tot;i++)
            {
                if(visit[i])continue;
                for(int j=0;j<26;j++)
                {
                    if(visit[trie[i][j]])continue;
                    a.m[i][trie[i][j]]++;
                }
            }
            for(int i=0;i<=tot+1;i++)
                a.m[i][tot+1]=1;
            cnt=tot+1;
            a=a^m; ll ans=0;
            for(int i=0;i<=cnt;i++)
                ans+=a.m[0][i];
            cnt=2;
            b.m[0][0]=26;b.m[0][1]=1;b.m[1][1]=1;
            b=b^m;
            ll tmp=b.m[0][0]+b.m[0][1];
           cout<<tmp-ans<<endl;
        }
    }
  • 相关阅读:
    erlang遍历目录
    C/C++ makefile自动生成工具(comake2,autotools,linux),希望能为开源做点微薄的贡献!
    shell 文件操作
    互联网分享知识(一)
    分页查询,你真的懂吗?
    awk神器
    Unicode编码解码在线转换工具
    awk 留底
    软件开发真的这么简单吗?
    php性能优化
  • 原文地址:https://www.cnblogs.com/huangdao/p/10810154.html
Copyright © 2011-2022 走看看