现在的位置: 首页 > 算法 > 正文

spoj 1676 Text Generator ac机+矩阵幂 好题!

2019年09月03日 算法 ⁄ 共 3466字 ⁄ 字号 评论关闭

SPOJ Problem Set (classical)

1676. Text Generator

Problem code: GEN

LoadingTime has been given a task these days. He is required to write a tool called Text Generator. This software is widely used among the kids who are under seven. It generates an article with the size of a given number L for users. If an article contains
at least one word which the users know, we consider it readable. Now, LoadingTime wants to know, how many readable articles can it generates, and he can improve his Text Generator. Could you help him??

Input

The input contains multiple test cases.

The first line of each test case contains two integer N (1 <= N <= 10), L (1 <= L <= 1000000). The following N lines contain N words representing the words knew by the users. All the words and the generated article only contain uppercase letters, and the length
of each word is not greater than 6.

Output

For each test case, your program should output a integer as LoadingTime required. As the number could be quite large, you only need to print the answer modulo 10007.

Example

Input:
2 2
A
B
2 10000
ABC
B

Output:
100
5960


Added by: Bin Jin
Date: 2007-07-05
Time limit: 10s
Source limit: 50000B
Memory limit: 256MB
Cluster: Pyramid (Intel Pentium III 733 MHz)
Languages: All except: C++ 4.0.0-8
Resource:  








题目给定n个熟悉的串,问长度为m且至少含一个熟悉串的方案数,m<=100万。逆向思维,用总的方案数减去不含熟悉串的方案数。

思路:先用ac自动机求出初始矩阵,初始矩阵A.matrix[i][j]表示从自动机的节点i走一步不经过熟悉串的结尾有几种方法可以走到节点j,然后用对A.matrix矩阵进行二分快速幂求A^L,其中A.matrix[i][j]表示从i到j经过L步不经过熟悉串的结尾的方法数。幂乘的时候注意尽量少用%mod。(当超过mod时才用%mod,详见代码),最后用26^L-sum(A.matrix[0][k],0<=k<sz),其中sz为ac机上的节点个数,但这样会T
= =。我们又注意到对于自动机节点i来说,如果它的cnt!=0,那么它并没有存在的意义。所以我们对ac机上cnt=0的点进行重新编码,建立初始矩阵,最后用26^L-sum(A.matrix[0][k],0<=k<sz'),sz'为ac机上cnt=0的个数。(详见程序)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=65;
const int sigma_size=26;
const int mod=10007;
int n,m,l,sz,head,tail;
struct node
{
    int cnt,id;
    node *next[sigma_size],*fail;
}trie[MAXN],*root,*que[MAXN];
struct AC
{
    node *createnode()
    {
        for(int k=0;k<sigma_size;k++)
            trie[sz].next[k]=NULL;
        trie[sz].fail=NULL;
        trie[sz].cnt=0,trie[sz].id=sz;
        return &trie[sz++];
    }
    void init()
    {
        sz=0;
        head=tail=0;
        root=createnode();
    }
    void insert(char *str)
    {
        node *p=root;
        int len=strlen(str);
        for(int i=0;i<len;i++)
        {
            int k=str[i]-'A';
            if(p->next[k]==NULL)
                p->next[k]=createnode();
            p=p->next[k];
        }
        p->cnt++;
    }
    void get_fail()
    {
        que[tail++]=root;
        while(head<tail)
        {
            node *p=que[head++];
            for(int k=0;k<sigma_size;k++)
                if(p->next[k])
                {
                    if(p==root)
                        p->next[k]->fail=root;
                    else
                        p->next[k]->fail=p->fail->next[k];
                    p->next[k]->cnt|=p->next[k]->fail->cnt;
                    que[tail++]=p->next[k];
                }
                else
                {
                    if(p==root)
                        p->next[k]=root;
                    else
                        p->next[k]=p->fail->next[k];
                }
        }
    }
}ac;
struct Matrix
{
    int matrix[MAXN][MAXN];
}E;
Matrix matrix_mul(Matrix a,Matrix b)
{
    Matrix c;
    for(int i=0;i<m;i++)
        for(int j=0;j<m;j++)
        {
            c.matrix[i][j]=0;
            for(int k=0;k<m;k++)
                if(a.matrix[i][k] && b.matrix[k][j])
                {
                    c.matrix[i][j]+=a.matrix[i][k]*b.matrix[k][j];
                    if(c.matrix[i][j]>=mod)
                        c.matrix[i][j]%=mod;
                }
        }
    return c;
}
Matrix matrix_pow(Matrix a,int k)
{
    Matrix c=E;
    while(k)
    {
        if(k&1)
            c=matrix_mul(c,a);
        a=matrix_mul(a,a);
        k>>=1;
    }
    return c;
}
int num_pow(int a,int k)
{
    int ans=1;
    while(k)
    {
        if(k&1)
        {
            ans*=a;
            if(ans>=mod)
                ans%=mod;
        }
        a=a*a; k>>=1;
        if(a>=mod)
            a%=mod;
    }
    return ans;
}
int main()
{
    //freopen("text.txt","r",stdin);
    for(int i=0;i<MAXN;i++)
        E.matrix[i][i]=1;
    while(~scanf("%d%d",&n,&l))
    {
        ac.init();
        char str[10];
        for(int i=0;i<n;i++)
        {
            scanf("%s",str);
            ac.insert(str);
        }
        ac.get_fail();
        Matrix A;
        int u=0,v,num;
        for(int i=0;i<sz;i++)
        if(!trie[i].cnt)
        {
            v=0;
            for(int j=0;j<sz;j++)
                if(!trie[j].cnt)
                {
                    num=0;
                    for(int k=0;k<sigma_size;k++)
                        if(trie[i].next[k]->id==trie[j].id)
                            num++;
                    A.matrix[u][v]=num;
                    v++;
                }
            u++;
        }
        m=u;
        int ans=num_pow(26,l);
        A=matrix_pow(A,l);
        int temp=0;
        for(int i=0;i<m;i++)
        {
            temp=(temp+A.matrix[0][i]);
            if(temp>=mod)
                temp%=mod;
        }
        ans-=temp;
        if(ans<0)
            ans+=mod;
        printf("%d\n",ans);
    }
    return 0;
}

抱歉!评论已关闭.