HDU-2243 考研路茫茫——单词情结(AC自动机)

题目大意:给n个单词,长度不超过L的单词有多少个包含n个单词中的至少一个单词。

题目分析:用长度不超过L的单词书目减去长度在L之内所有不包含任何一个单词的书目。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

# define LL long long
# define ULL unsigned long long

struct Matrix
{
    int n;
    ULL ele[35][35];
    Matrix(int _n):n(_n){
        for(int i=0;i<n;++i) for(int j=0;j<n;++j)
            ele[i][j]=0;
    }
};
int ch[35][26];
int fail[35],cnt;
bool word[35];

void init()
{
    cnt=0;
    memset(ch,-1,sizeof(ch));
    memset(word,false,sizeof(word));
}

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

void insert(char *s)
{
    int n=strlen(s);
    int r=0;
    for(int i=0;i<n;++i){
        int c=idx(s[i]);
        if(ch[r][c]==-1) ch[r][c]=++cnt;
        r=ch[r][c];
    }
    word[r]=true;
}

void getFail()
{
    queue<int>q;
    fail[0]=0;
    for(int i=0;i<26;++i){
		if(ch[0][i]==-1){
			ch[0][i]=0;
		}else{
			fail[ch[0][i]]=0;
			q.push(ch[0][i]);
		}
    }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(word[fail[u]]) word[u]=true;
        for(int i=0;i<26;++i){
            if(ch[u][i]==-1)
                ch[u][i]=ch[fail[u]][i];
            else{
                fail[ch[u][i]]=ch[fail[u]][i];
                q.push(ch[u][i]);
            }
        }
    }
}

Matrix getMatrix()
{
	Matrix mat(cnt+1);
	for(int i=0;i<mat.n;++i)
		for(int j=0;j<26;++j) if(!word[ch[i][j]])
			++mat.ele[i][ch[i][j]];
    ++mat.n;
    for(int i=0;i<mat.n;++i){
		mat.ele[mat.n-1][i]=0;
		mat.ele[i][mat.n-1]=1;
    }
    return mat;
}

Matrix mul(Matrix a,Matrix b)
{
    Matrix c(a.n);
    for(int i=0;i<c.n;++i) for(int j=0;j<c.n;++j)
		for(int k=0;k<c.n;++k) c.ele[i][j]+=a.ele[i][k]*b.ele[k][j];
    return c;
}

Matrix myPow(Matrix a,LL k)
{
    Matrix mat(a.n);
	for(int i=0;i<mat.n;++i) mat.ele[i][i]=1;
	while(k>0){
		if(k&1) mat=mul(mat,a);
		a=mul(a,a);
		k>>=1;
	}
    return mat;
}

ULL getSum(LL x)
{
	Matrix mat(2);
	mat.ele[0][0]=26;
	mat.ele[0][1]=1;
	mat.ele[1][0]=0;
	mat.ele[1][1]=1;
	mat=myPow(mat,x);
	return mat.ele[0][1];
}

char prefix[8];

int main()
{
    int n;
    LL L;	
    while(~scanf("%d%lld",&n,&L))
    {
		init();
        for(int i=0;i<n;++i){
            scanf("%s",prefix);
            insert(prefix);
        }
        getFail();
        Matrix mat=getMatrix();
        mat=myPow(mat,L+1);
        ULL ans1=mat.ele[0][mat.n-1];
        ULL ans2=getSum(L+1);
        cout<<ans2-ans1<<endl;
    }
    return 0;
}

 

posted @ 2016-10-21 16:00  20143605  阅读(187)  评论(0编辑  收藏  举报