HDU2243 AC自动机 + 矩阵快速幂

题意:给定你m个模式串,问你长度小于等于L的符串中,有多少包含着这些模式串。

思路:这个题的思路求解类似于POJ2778,只不过那一题求未包含模式串,而这一题求的是包含模式串的数量,可构造字符串的总数量减去不包含模式串的字符串数量,就可以得到包含模式串的数量。
但还有一个问题就是L < 2^31,规模太大 肯定不能直接求解小于等于L的字符串的数量。在这里插入图片描述
由此可得这个问题便可以用矩阵快速幂求解来完成,因此这个题目就是AC自动build一下,再加上矩阵快速幂的构造来完成的,很类似与poj2778,注意问题也和上一题相似

AC代码:

#include <bits/stdc++.h>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iostream>
// 和前面一题 差不多 在另外加上一个 矩阵快速幂的求解过程
// 求一个很大的序列的时候 可以尝试用矩阵写出来 看前后项之间的关系 从而 推得 能否用矩阵快速幂的方法求解
using namespace std;
typedef unsigned long long ull;
const int MAX_tot = 37;
const int MAXN = 17;

struct Matrix
{
    
    
	ull mat[MAX_tot][MAX_tot];
	int n;
	Matrix(){
    
    }
	Matrix(int num){
    
    
		n = num;
		for(int i = 0;i < n;i ++){
    
    
			for(int j = 0;j < n;j ++)
				mat[i][j] = 0;
		}
	}
};

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

Matrix quickpow(Matrix a,int n)
{
    
    
	Matrix E = Matrix(a.n);
	for(int i = 0;i < a.n;i ++) E.mat[i][i] = 1;//单位矩阵
	while(n){
    
    
		if(n&1) E = mul(E,a);
		a = mul(a,a);
		n >>= 1;
	}
	return E;
}

struct Aca
{
    
    
	int size,Next[MAX_tot][26],fail[MAX_tot],end[MAX_tot];

	queue<int>q;

	void init()
	{
    
    
		while(!q.empty()) q.pop();
		for(int i = 0;i < MAX_tot;i ++){
    
    
			fail[i] = end[i]= 0;
			for(int c = 0;c < 26;c ++) Next[i][c] = 0;
		}
		size = 1;
	}

	void insert(char *s)
	{
    
    
		int len = strlen(s),p = 1;
		for(int i = 0;i < len;i ++){
    
    
			int ch = s[i] - 'a';
			if(!Next[p][ch]) Next[p][ch] = ++size;
			p = Next[p][ch];
		}
		end[p] = 1;
	}

	void build()
	{
    
    
		for(int i = 0;i < 26;i ++) Next[0][i] = 1;
		q.push(1);
		fail[1] = 0;
		while(!q.empty()){
    
    
			int p = q.front();
			q.pop();
			for(int i = 0;i < 26;i ++){
    
    
				int now = Next[p][i];
				int fafail = fail[p];
				if(!now){
    
    
					Next[p][i] = Next[fafail][i];
					continue;
				}
				fail[now] = Next[fafail][i];
				q.push(now);
			}
			end[p] |= end[fail[p]];//利用父节点 更新当前节点的信息
		}
	}

	Matrix getmatrix()
	{
    
    
		Matrix tmp = Matrix(size+1);
		for(int i = 1;i <= size;i ++){
    
    
			for(int j = 0;j < 26;j ++){
    
    
				if(end[Next[i][j]]) continue;
				tmp.mat[i-1][Next[i][j]-1]++;
			}
		}
		for(int i = 1;i <= size+1;i ++) tmp.mat[i-1][size] = 1;
		return tmp;
	}

}aca;

void opMatrix(Matrix a)
{
    
    
	for(int i = 0;i < a.n;i ++){
    
    
		for(int j = 0;j < a.n;j ++){
    
    
			printf(j == a.n-1?"%d\n":"%d ",a.mat[i][j]);
		}
	}
}

char s[MAXN];

int main()
{
    
    
	int n,l;
	while(~scanf("%d%d",&n,&l)){
    
    
		aca.init();

		for(int i = 1;i <= n;i ++){
    
    
			scanf("%s",s);
			aca.insert(s);
		}

		aca.build();

		Matrix A = aca.getmatrix();
		//opMatrix(A);
		ull res = 0;
		A = quickpow(A,l);
		//opMatrix(A);
		for(int i = 0;i < A.n;i ++){
    
    
			res += A.mat[0][i];
		}
		res--;
		//printf("%d\n",res);
		//opMatrix(ansA);
		Matrix T = Matrix(2);
		T.mat[0][0] = 26,T.mat[0][1] = 1,T.mat[1][1] = 1;
		T = quickpow(T,l);
		ull ans = T.mat[0][0] + T.mat[0][1];
		ans--;
		ans -= res;
		cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45672411/article/details/108370962
今日推荐