SPOJ 1676 Text Generator (ac自动机+矩阵优化)

题意:给出n个单词,求这些单词能组成的文章个数,文章的单词数L个。

题解:

各种TL,一个黑色的晚上。不知道为什么,自己写的矩阵乘法异常的慢,从类改成写简陋的C格式,都TL了,发现是取模太多次的缘故,于是改成加完在摸,结果wa了,坑爹,然后改成longlong TL了,简直无情啊。最后用了无符号int即不会爆int也不像longlong那么耗费时间。于是就过了。。。。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef long long ll;
//typedef unsigned __int64 Ull;
const int oo=0x3f3f3f3f;
//const ll OO=1LL<<61;
const int MOD=10007;
const int maxn=1005;
const int SIZE=70;
const int type=26;
char str[10];
unsigned maze[SIZE][SIZE],temp[SIZE][SIZE],res[SIZE][SIZE];
int n;

void Copy(unsigned x[][SIZE],unsigned y[][SIZE])
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            x[i][j]=y[i][j];
}

void Matrix_Mul(unsigned x[][SIZE],unsigned y[][SIZE])
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            temp[i][j]=0;
            for(int k=0;k<n;k++)
                temp[i][j]+=x[i][k]*y[k][j];
            temp[i][j]%=MOD;
        }
}

void Matrix_pow(unsigned x[][SIZE],int k)
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            res[i][j]=(i==j);
    while(k)
    {
        if(k&1)
        {
            Matrix_Mul(res,x);
            Copy(res,temp);
        }
        Matrix_Mul(x,x);
        Copy(x,temp);
        k>>=1;
    }
}

int quick_pow(int a,int k)
{
    int ans=1;
    while(k)
    {
        if(k&1)
            ans=ans*a%MOD;
        a=a*a%MOD;
        k>>=1;
    }
    return ans;
}

struct ACautomaton
{
    int next[SIZE][type],fail[SIZE],word[SIZE];
    int cnt,root;

    int newNode()
    {
        for(int i=0;i<type;i++)
            next[cnt][i]=-1;
        word[cnt++]=0;
        return cnt-1;
    }

    void Init()
    {
        cnt=0;
        root=newNode();
    }

    void Insert(char buff[])
    {
        int now=root;
        int len=strlen(buff);
        for(int i=0,k;i<len;i++)
        {
            k=buff[i]-'A';
            if(next[now][k]==-1)
                next[now][k]=newNode();
            now=next[now][k];
        }
        word[now]=1;
    }

    void build()
    {
        fail[root]=root;
        int now=root;
        queue<int>Q;
        for(int i=0;i<type;i++)
        {
            if(next[now][i]==-1)
                next[now][i]=root;
            else
            {
                fail[next[now][i]]=root;
                Q.push(next[now][i]);
            }
        }
        while(!Q.empty())
        {
            now=Q.front();
            Q.pop();
            if(word[fail[now]]) word[now]=1;
            for(int i=0;i<type;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]);
                }
            }
        }
    }

    int solve(int L)
    {
        n=cnt;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                maze[i][j]=0;
        for(int i=0;i<cnt;i++)
            for(int j=0;j<type;j++)
            {
                int k=next[i][j];
                if(!word[k])
                    maze[i][k]++;
            }
        Matrix_pow(maze,L);
        int ans=0;
        for(int i=0;i<n;i++)
            ans=(ans+res[0][i]+MOD)%MOD;
        int sum=quick_pow(26,L);
        return (sum-ans+MOD)%MOD;
    }

}ac;

int main()
{
    int N,L;
    while(scanf("%d %d",&N,&L)!=EOF)
    {
        ac.Init();
        for(int i=1;i<=N;i++)
        {
            scanf("%s",str);
            ac.Insert(str);
        }
        ac.build();
        printf("%d\n",ac.solve(L));
    }
    return 0;
}




你可能感兴趣的:(SPOJ 1676 Text Generator (ac自动机+矩阵优化))