HDU2243 考研路茫茫――单词情结 AC自动机

题意:求不包含给定的串且长度不大于m的串的个数

思路:这题是POJ2778的加强版,方法是求出包含给定的串的个数,再用总的方法数去减这个数字,就是得到不包含给定的串的个数。

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N=40;
const int CHAR=26;
typedef unsigned long long ll;
int Hash(char c){
	return c-'a';
}
struct Trie
{
	int next[N][CHAR],fail[N],end[N];
	int root,L;
	int newnode()
	{
		for(int i = 0;i < CHAR;i++)
			next[L][i] = -1;

		end[L++] = 0;
		return L-1;
	}
	void init()
	{
		L = 0;
		root = newnode();
	}
	void insert(char buf[])
	{
		int len = strlen(buf);
		int now = root;
		for(int i = 0;i < len;i++)
		{
			int u=Hash(buf[i]);
			if(next[now][u] == -1)
				next[now][u] = newnode();
			now = next[now][u];
		}
		end[now]=1;
	}
	void build()
	{
		queueQ;
		fail[root] = root;
		for(int i = 0;i < CHAR;i++)
			if(next[root][i] == -1)
				next[root][i] = root;
			else
			{
				fail[next[root][i]] = root;
				Q.push(next[root][i]);
			}
			while( !Q.empty() )
			{
				int now = Q.front();
				Q.pop();
				for(int i = 0;i < CHAR;i++)
					if(next[now][i] == -1)
						next[now][i] = next[fail[now]][i];
					else
					{
						fail[next[now][i]]=next[fail[now]][i];
						end[next[now][i]]|=end[next[fail[now]][i]];//需注意
						Q.push(next[now][i]);
					}
			}
	}
};
char s[105];
Trie ac;
struct Mat{
	ll a[40][40];
	int sz;
	Mat(){}
	Mat(int _x):sz(_x){
		for(int i=0;i<=_x;i++)
			for(int j=0;j<=_x;j++)
				a[i][j]=0;
	}
	Mat operator * (const Mat &b)const{
		Mat ret(sz);
		for(int i=0;i<=sz;i++)
			for(int j=0;j<=sz;j++)
				for(int k=0;k<=sz;k++){
					ret.a[i][j]+=(ll)a[i][k]*b.a[k][j];
				}
		return ret;
	}
	Mat operator ^(int t){
		Mat ret(sz);
		for(int i=0;i<=sz;i++)ret.a[i][i]=1;
		while(t){
			if(t&1)ret=ret * *this;
			t>>=1;
			*this=*this * *this;
		}
		return ret;
	}
	void out(){
		for(int i=0;i<=sz;i++){
			for(int j=0;j<=sz;j++){
				printf("%d,",a[i][j]);
			}
			printf("\n");
		}
	}
};
ll Pow(ll a,ll b){
    ll ret=1;
    while(b){
        if(b&1)ret=ret*a;
        b>>=1;
        a=a*a;
    }
    return ret;
}
int main()
{
	freopen("C_in.txt","r",stdin);
	int T;
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		ac.init();
		for(int i = 1;i<=n;i++){
			scanf("%s",s);
			ac.insert(s);
		}
		ac.build();
		Mat A(ac.L);
		Mat B(ac.L);
		for(int i=0;i


你可能感兴趣的:(AC自动机)