您的位置:首页 > 其它

POJ 1625 Censored! AC自动机 简单DP 高精度

2013-01-28 22:52 459 查看
题意:一个中语言中进制特定的序列出现,问在长度为m的句子中,有几个合法的句子。

做法:高精度方面果断模板。然后划分状态,以当前的字符在tire树的位置,以及当前的长度为状态,暴力一下就可以了。

对于这种树中遍历行的状态做的比较少,而且coding的能力也比较汗啊

#include <iostream>
#include<cstring>
#include<cstdio>
#include<deque>
#include<map>
#define CC(A, x)    memset(A, x, sizeof(A))
#define LMT 502
#define CHD 52
using namespace std;
bool word[LMT];
int siz,wiz,gra[LMT][CHD],fail[LMT];
map<char,int>pos;
void insert(char sor[])
{
    int index,current =0;
    for(int i=0;sor[i];i++)
    {
            index=pos[sor[i]];
        if(!gra[current][index])gra[current][index]=siz++;
        current=gra[current][index];
    }
    word[current]|=1;
}
void build_ac(void)
{
    int current,v;
    deque<int>q;
    q.clear();
    for(int i=0;i<wiz;i++)
    if(gra[0][i])q.push_back(gra[0][i]);
    while(!q.empty())
    {
        current=q.front();
        q.pop_front();
        for(int i=0;i<wiz;i++)
        if(gra[current][i])
        {
            v=gra[current][i];
            fail[v]=gra[fail[current]][i];
            word[v]|=word[fail[v]];
            q.push_back(v);
        }
        else gra[current][i]=gra[fail[current]][i];
    }
}
struct Number{
    Number(){CC(A,0); A[0]=1;}
    void set(int x){CC(A,0); A[0]=1; A[1]=x;}
    void print(){
        cout<<A[A[0]];
        for (int i=A[0]-1; i>0; i--){
            if (A[i]==0){cout<<"0000"; continue;}
            for (int k=10; k*A[i]<MOD; k*=10) cout<<'0';
            cout<<A[i];
        }
        cout<<endl;
    }
    Number operator + (const Number& B){
        Number C;
        C[0]=max(A[0], B[0]);
        for (int i=1; i<=C[0]; i++)
            C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
        if (C[C[0]+1] > 0) C[0]++;
        return C;
    }
    Number operator * (const Number& B){
        Number C;
        C[0]=A[0]+B[0];
        for (int i=1; i<=A[0]; i++)
            for (int j=1; j<=B[0]; j++){
                C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
            }
        if (C[C[0]] == 0) C[0]--;
        return C;
    }
    int& operator [] (int p) {return A[p];}
    const int& operator [] (int p) const {return A[p];}
    int A[25];
    enum{MOD = 10000};
};
Number dp[55][LMT];
void init(void)
{
    siz=1;
    memset(word,0,sizeof(word));
    memset(fail,0,sizeof(fail));
    memset(gra,0,sizeof(gra));
    for(int i=0;i<55;i++)
      for(int j=0;j<LMT;j++)
      dp[i][j].set(0);
    pos.clear();
}
void solve(int len)
{
    int v;
    Number ans;
    dp[0][0].set(1);
    for(int i=0;i<len;i++)
       for(int j=0;j<siz;j++)
         for(int t=0;t<wiz;t++)
         {
             v=gra[j][t];
             if(!word[v])
             dp[i+1][v]=dp[i+1][v]+dp[i][j];
         }
         for(int i=0;i<siz;i++)
         ans=ans+dp[len][i];
         ans.print();
}
int main()
{
    int m,p;
    char sec[60];
    while(~scanf("%d%d%d",&wiz,&m,&p))
    {
        init();//init()里面加上wiz=0铸成大错...中途改程序的时候要小心了
        scanf("%s",sec);
        for(int i=0;sec[i];i++)
        pos[sec[i]]=i;
        for(int i=0;i<p;i++)
        {
            scanf("%s",sec);
            insert(sec);
        }
        build_ac();
        solve(m);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: