AC自动机+矩阵+二分

原创 2012年03月22日 17:21:01

自动机+矩阵快速幂+二分

题目:考研路茫茫——单词情结

题目大意:给出n个串,求至少包含一个串的长度不操过L的串的个数

思路:首先就是思路转化,自动机一般求的是不包含危险串的字串的个数,因此我们就反过来求,先求所有可能的串26+26^2+26^3…+26^L,然后不可能包含的串的个数,即长度为1,2,。。。,L的不包含给定的n个串的个数。然后用全部的减去这个,就是我们要的答案。

我们知道x^y可用快速幂求,那么幂的前n项和呢?

x^1+x^2+x^3+⋯+x^L=(x^1+x^2+⋯+x^(L/2) )*x^((L+1)/2) (当l是偶数时)

奇数时再加个中间项x^((L+1)/2)便可

这样就可以二分求解幂的前n项和了

对于一个图来说,他的邻接矩阵是A,离散数学告诉我们A^1是两点件距离为1的路径条数,A^2是两点间距离为2的路径条数,那么长度不超过L的距离和便是

A^1+A^2+…+A^L 这个也可用上面的二分进行求解

 

提交情况:TLE数次,原因长度应该是long long类型

体会 :好题


/*
	题目 :http://acm.hdu.edu.cn/showproblem.php?pid=2243
	考研路茫茫——单词情结
	给出n个串, 求至少包含一个串的长度不操过L的串的个数。利用图的n次幂表示两点间路径长度是n的个数。
	再利用二分求幂的前n项和
 */

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

#define maxn 7
#define maxnl 6
#define maxstate 30
#define size 26
typedef unsigned long long u64;

struct matrix{
	u64 mat[maxstate][maxstate];
	int n, m;
	matrix(){n = m = maxstate; }
	void init(int _n, int _m){ n = _n, m = _m; }
	/* 构造零矩阵 */
	void setZero(){ memset(mat, 0, sizeof(mat)); }
	/* 构造单位矩阵 */
	void setOne(){
		for(int i = 0; i < n; ++ i){
			for(int j = 0; j < m; ++ j){
				mat[i][j] = (i == j);
			}
		}
	}
} matx;

/* 矩阵加法 */
matrix operator + (const matrix &A, const matrix &B){
	matrix temp;
	temp.init(A.n, A.m);
	for(int i = 0; i < A.n; ++ i){
		for(int j = 0; j < A.m; ++ j){
			temp.mat[i][j] = A.mat[i][j] + B.mat[i][j];
		}
	}
	return temp;
}
/* 矩阵乘法 */
matrix operator * (const matrix &A, const matrix &B){
	matrix temp;
	temp.init(A.n, B.m);  
	temp.setZero();
	for(int k = 0; k < A.m; ++ k){
		for(int i = 0; i < A.n; ++ i){
			if(A.mat[i][k])
				for(int j = 0; j < B.m; ++ j){
					temp.mat[i][j] += A.mat[i][k] * B.mat[k][j];
				}
		}
	}
	return temp;
}
/* 矩阵幂 */
matrix operator ^ (matrix A, u64 k){
	matrix ans;
	ans.init(A.n, A.m);
	ans.setOne();
	while(k){
		if(k & 1) ans = ans * A;
		A = A * A;
		k >>= 1;
	}
	return ans;
}

struct automatonNode{
	bool real;
	int id;
	automatonNode* next[size],* fail;
	void clear(){
		memset(next, NULL, sizeof(next));
		real = 0;
		id = -1;
	}
};

struct automaton{
	automatonNode* root, * link,** queue;
	int head, tail, ad, tot;
	automaton(){ 
		link = new automatonNode[maxn * maxnl];
		queue = new automatonNode*[maxn * maxnl];
	}
	~automaton(){
		delete[] link;
		delete[] queue;
	}
	/* 初始化根节点 */
	void clear(){
		ad = 0;
		root = &link[ad ++];
		root->clear();
		root->fail = root;
	}
	/* 转换字符 */
	int cg(char ch){ return ch - 'a'; }
	/* 插入串 */
	void insert(char *str){
		automatonNode* rt = root;
		for(int i = 0; str[i] != '\0'; ++ i){
			if(rt->next[cg(str[i])] == NULL){
				rt->next[cg(str[i])] = &link[ad ++];
				rt->next[cg(str[i])]->clear();
			}
			rt = rt->next[cg(str[i])];
		}
		rt->real = 1;
	}
	/* 建立自动机 */
	void built(){
		automatonNode * fa;
		head = tail = tot = 0;
		queue[tail ++] = root;
		while(head != tail){
			fa = queue[head ++];
			if(fa->real == 0 && fa->id == -1) fa->id = tot ++;
			for(int i = 0; i < size; ++ i){
				if(fa->next[i] == NULL){
					fa->next[i] = (fa == root) ? (root) : (fa->fail->next[i]);
				}
				else{
					fa->next[i]->fail = (fa == root) ? (root) : (fa->fail->next[i]);
					fa->next[i]->real |= fa->next[i]->fail->real;
					queue[tail ++] = fa->next[i];
					if(fa->real) fa->next[i]->real = 1;
				}
			}
		}
	}
	/* 建立自动机的矩阵 */
	void buitMatrix(){
		automatonNode *rt;
		head = 0;
		matx.setZero();
		matx.init(tot, tot);
		while(head < tail){
			rt = queue[head ++];
			if(rt->real) continue;
			for(int i = 0; i < size; ++ i){
				if(rt->next[i]->real == 0)
					matx.mat[rt->id][rt->next[i]->id] ++;
			}
		}
	}
};

u64 numPowerMod(u64 x, u64 k){
	u64 ans = 1;
	while(k){
		if(k & 1) ans *= x;
		x *= x;
		k >>= 1;
	}
	return ans;
}
u64 numSumPowerMod(u64 x, u64 k){
	if(k == 1) return x;
	u64 sumTemp = numSumPowerMod(x, k >> 1), numTemp = numPowerMod(x, (k + 1) >> 1);
	if(k & 1) return sumTemp + sumTemp * numTemp + numTemp;
	else return sumTemp + sumTemp * numTemp;
}
matrix sumTemp, numTemp;
matrix matrixSumPowerMod(u64 k){
	if(k == 1) return matx;
	sumTemp = matrixSumPowerMod(k >> 1);
	numTemp = matx ^ ((k + 1) >> 1);
	if(k & 1) return sumTemp + sumTemp * numTemp + numTemp;
	else return sumTemp + sumTemp * numTemp;
}

void slove(u64 len){
	u64 ans = numSumPowerMod(26, len);
	matx = matrixSumPowerMod(len);
	for(int i = 0; i < matx.m; ++ i){
		ans -= matx.mat[0][i];
	}
	printf("%I64u\n", ans);
}

int main(){
	u64 ans;
	u64 n, l;
	char str[maxnl];
	automaton autom;
	while(~scanf("%I64u %I64u", &n, &l)){
		autom.clear();
		for(int i = 0; i < n; ++ i){
			scanf("%s", str);
			autom.insert(str);
		}
		autom.built();
		autom.buitMatrix();
		slove(l);
	} 
	return 0;
}




HDU 2243:考研路茫茫——单词情结(AC自动机+矩阵二分幕和)

考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To...
  • wugj03
  • wugj03
  • 2011年09月11日 11:19
  • 768

hdu2243---考研路茫茫——单词情结(AC自动机+矩阵+二分)

首先对2^64取模的话,可以直接用unsigned long long,这样溢出部分就是取模后的结果了 方法类似POJ2778传送门 只不过这里要统计长度不超过m的方案 我们先统计出长度为...

poj 2778 AC自动机+DP+矩阵快速幂

#include #include #include #include using namespace std; typedef __int64 type; const int kind=4; //...

【hdu2243】【AC自动机】【矩阵乘法】考研路茫茫——单词情结

首先利用补集转化思想,将问题转化为求一个词根都不包含的单词有多少种。 可以想到将所有的词根建为AC自动机,然后使用DP求解。 由于长度范围很大,可以使用矩阵乘法加速。 并且题目中要求的是“长度不...
  • njlcazl
  • njlcazl
  • 2013年05月11日 16:55
  • 534

poj2778 DNA Sequence(AC自动机+矩阵快速幂)

Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's v...

poj2778 DNA Sequence(AC自动机+矩阵快速幂)

题目链接:点击打开链接 题意描述:给m字符串,这m个字符串是带有病毒的DNA。然后问一个长度为n的字符串不带有任何病毒有多少中可能?所有字符串之后ACGT这几个字符串组成 解题思路:AC自动机+矩...

【bzoj2553】【beijing2008】【禁忌】【AC自动机+矩阵乘法】

Description        Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平。而后,Koishi恢复了读心的能力…...

poj 2778 DNA Sequence //AC自动机+矩阵乘法

DNA SequenceTime Limit: 1000MS Memory Limit: 65536KTotal Submissions: 5080 Accepted: 1766Description...
  • hqd_acm
  • hqd_acm
  • 2011年04月22日 21:59
  • 1227

POJ 2778 DNA Sequence(AC自动机+矩阵)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove 题目:长度为N的DNA串不...

POJ2778---DNA Sequence(AC自动机+矩阵)

Description It’s well known that DNA Sequence is a sequence only contains A, C, T and G, and it’s v...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AC自动机+矩阵+二分
举报原因:
原因补充:

(最多只允许输入30个字)