HDU2243 AC automata + matrix fast power

Meaning of the question: Given you m pattern strings, ask you how many of the strings whose length is less than or equal to L contain these pattern strings.

Idea: The solution of this question is similar to POJ2778 , except that the question does not contain the pattern string, and this question asks for the number of pattern strings. The total number of strings can be constructed minus the characters that do not contain the pattern string. The number of strings, you can get the number of strings containing patterns.
But another problem is that L <2^31. If the scale is too large, it is impossible to directly solve the number of strings less than or equal to L. Insert picture description here
From this it can be seen that this problem can be solved by the matrix fast power solution, so this problem is automatically built by AC, coupled with the matrix fast power construction to complete, very similar to poj2778, note that the problem is also similar to the previous problem

AC code:

#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;
}

Guess you like

Origin blog.csdn.net/weixin_45672411/article/details/108370962