POJ 1625 Censored!

給定p個模式串,求長度爲m<=50的串中不包含任何模式串的串的種類數,字符僅由給出的n個字符構成,用mp數組標記下。然後和之前的幾道類似,利用end和next數組得到轉態轉移數組,然後由於題目數據不像之前的那麼大,可以用dp[i][j]來進行狀態轉移,i代表當前串長度,j爲當前狀態。但是由於答案很大需要用到高精度。代碼如下
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

int N;
int mp[300];

struct Matrix
{
    long long mat[110][110];
    int n;
    Matrix(){}
    Matrix(int _n)
    {
        n=_n;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                mat[i][j] = 0;
    }
    Matrix operator *(const Matrix &b)const
    {
        Matrix ret = Matrix(n);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                for(int k=0;k<n;k++)
                    ret.mat[i][j]+=mat[i][k]*b.mat[k][j];
        return ret;
    }
};
struct Tree
{
	int next[110][256],end[110],fail[110];
	int L,root;
	int newnode()
	{
		for(int i=0;i<255;i++)
		{
			next[L][i]=-1;
		}
		end[L++]=0;
		return L-1;
	}
	void init()
	{
		L=0;
		root=newnode();
	}
	void insert(char *s)
	{
		int len=strlen(s);
		int p=root;
		for(int i=0;i<len;i++)
		{
			if(next[p][mp[s[i]]]==-1)
			{
				next[p][mp[s[i]]]=newnode();
			}
			p=next[p][mp[s[i]]];
		}
		end[p]++;
	}
	void build()
	{
		queue<int>q;
		int p=root;
		fail[root]=root;
		for(int i=0;i<255;i++)
		{
			if(next[p][i]==-1)
			{
				next[p][i]=root;
			}
			else
			{
				fail[next[p][i]]=root;
				q.push(next[p][i]);
			}
		}
		while(!q.empty())
		{
			p=q.front();
			q.pop();
			if(end[fail[p]]) end[p]=1;
			for(int i=0;i<255;i++)
			{
				if(next[p][i]==-1)
				{
					next[p][i]=next[fail[p]][i];
				}
				else
				{
					fail[next[p][i]]=next[fail[p]][i];
					q.push(next[p][i]);
				}
			}
		}
	}
	void query(char *s)
	{
		int len=strlen(s);
		int p=root,ans=0;
		for(int i=0;i<len;i++)
		{
			int id=s[i]-'a';
			p=next[p][id];
			int temp=p;
			while(temp!=root)
			{
				if(end[temp])
				{
					ans+=end[temp];
					end[temp]=0;
				}
				temp=fail[temp];
			}
		}
	}
	Matrix getMatrix()
	{
		Matrix a(L);
		for(int i=0;i<a.n;i++)
		{
			for(int j=0;j<N;j++)
			{
				if(end[next[i][j]]==0)
				a.mat[i][next[i][j]]++;
			}
		}
		return a;
	}
	void debug()
    {
        for(int i = 0;i < L;i++)
        {
            printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
            for(int j = 0;j < 26;j++)
                printf("%2d",next[i][j]);
            printf("]\n");
        }
    }
};

struct BigInt
{
    const static int mod = 10000;
    const static int DLEN = 4;
    int a[600],len;
    BigInt()
    {
        memset(a,0,sizeof(a));
        len = 1;
    }
    BigInt(int v)
    {
        memset(a,0,sizeof(a));
        len = 0;
        do
        {
            a[len++] = v%mod;
            v /= mod;
        }while(v);
    }
    BigInt(const char s[])
    {
        memset(a,0,sizeof(a));
        int L = strlen(s);
        len = L/DLEN;
        if(L%DLEN)len++;
        int index = 0;
        for(int i = L-1;i >= 0;i -= DLEN)
        {
            int t = 0;
            int k = i - DLEN + 1;
            if(k < 0)k = 0;
            for(int j = k;j <= i;j++)
                t = t*10 + s[j] - '0';
            a[index++] = t;
        }
    }
    BigInt operator +(const BigInt &b)const
    {
        BigInt res;
        res.len = max(len,b.len);
        for(int i = 0;i <= res.len;i++)
            res.a[i] = 0;
        for(int i = 0;i < res.len;i++)
        {
            res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0);
            res.a[i+1] += res.a[i]/mod;
            res.a[i] %= mod;
        }
        if(res.a[res.len] > 0)res.len++;
        return res;
    }
    BigInt operator *(const BigInt &b)const
    {
        BigInt res;
        for(int i = 0; i < len;i++)
        {
            int up = 0;
            for(int j = 0;j < b.len;j++)
            {
                int temp = a[i]*b.a[j] + res.a[i+j] + up;
                res.a[i+j] = temp%mod;
                up = temp/mod;
            }
            if(up != 0)
                res.a[i + b.len] = up;
        }
        res.len = len + b.len;
        while(res.a[res.len - 1] == 0 &&res.len > 1)res.len--;
        return res;
    }
    void output()
    {
        printf("%d",a[len-1]);
        for(int i = len-2;i >=0 ;i--)
            printf("%04d",a[i]);
        printf("\n");
    }
};

Tree ac;
char s[55];
BigInt dp[2][110];
int main()
{
	int m,p;
	while(~scanf("%d %d %d",&N,&m,&p))
	{
		scanf("%s",s);
		for(int i=0;i<N;i++)
		mp[s[i]]=i;
		ac.init();
		for(int i=0;i<p;i++)
		{
			scanf("%s",s);
			ac.insert(s);
		}
		ac.build();
		Matrix a=ac.getMatrix();
		int now=0;
		dp[now][0]=1;
		for(int i=1;i<a.n;i++)
		{
			dp[now][i]=0;
		}
		for(int i=0;i<m;i++)
		{
			now^=1;
			for(int j=0;j<a.n;j++)
			{
				dp[now][j]=0;
			}
			for(int j=0;j<a.n;j++)
			{
				for(int k=0;k<a.n;k++)
				{
					if(a.mat[j][k]>0)
					{
						dp[now][k]=dp[now][k]+dp[now^1][j]*a.mat[j][k];
					}
				}
			}
		}
		BigInt ans=0;
		for(int i=0;i<a.n;i++)
		{
			ans=ans+dp[now][i];
		}
		ans.output();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章