AOJ1127 Non Absorbing DFA(自动机+DP)from ASC2

A - Non Absorbing DFA

Time Limit:  10000/5000MS (Java/Others)  Memory Limit:  128000/64000KB (Java/Others)
Problem Description

      In the theory of compilers and languages finite state machines, also known as finite automata are widely used. Deterministic finite automation (DFA) is an ordered set <Σ, U, s, T, φ>where Σ is the finite set called input alphabet, U is the finite set of states, s ∈U is the initial state, T ⊂ U is the set of terminal states and φ : U × Σ → U is the transition function.

      The input of the automation is the string α over Σ. Initially the automation is in state s. Each step it reads the first character c of the input string and changes its state to φ(u, c) where u is the current state. After that the first character of the input string is removed and the step repeats. If when its input string is empty the automation is in the terminal state, it is said that it accepts the initial string α, in the other case it rejects it.

      In some cases to simplify the automation the concept of nonabsorbing edges is introduced. That is, in addition to φ the function Х : U × Σ → {0, 1} is introduced and when making a transition from some state u with some character c, the leading character is removed from the input string only if Х(u, c) = 0. If Х(u, c) = 1, the input string is kept intact and next transition is performed with the new state and the same character.

      It is said that such automation accepts some string α if after a number of steps it transits to the terminal state and the input string becomes empty.

      Your task is given the DFA with nonabsorbing edges to compute the number of strings of the given length N that it accepts.

Input

      The first line of the input file contains Σ - a subset of the English alphabet, several different small letters. Next line contains K = |U| - the number of states of the automation (1 ≤ K ≤ 1000). Let states be numbered from 1 to K. Next line contains S (1 ≤ S ≤ K) - the initial state, followed by L = |T| - the number of terminal states and then L different integer numbers ranging from 1 to K - the numbers of terminal states.

      Next K lines contain |Σ| integer numbers each and define φ. Next K lines define Х in a similar way. The last line of the input file contains N(1 ≤ N ≤ 60).

Output
      Output the only number - the number of different strings of length N over Σ that the given DFA accepts.
Sample Input
ab
2
1 1 2
2 1
1 2
0 1
0 0
3
Sample Output
2
Hint
In the given example the two strings accepted by the automation are “aaa” and “abb”.


解题思路:

1.预处理从第i个字符开始,第st状态遇上字符ch,能转移到第i+1个字符的自动机的状态tmp[st][ch],不能转移就记为-1

2.用dp[i][j]记录考虑到第i个字符自动机上的状态为j的种数,转移即可。

要用大数,被大数模板坑了,红书上的大数略屌。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
int go[1010][30],delay[1010][30],tmp[1010][30];
char str[30];
int k,S,L,n,l;
int end[1010];

void init(){
    memset(end,0,sizeof end);
}

void read(){
    scanf("%d%d%d",&k,&S,&L);
    int x;
    for(int i=0;i<L;i++){
        scanf("%d",&x);
        end[x]=1;
    }
    l=strlen(str);
    for(int i=1;i<=k;i++){
        for(int j=0;j<l;j++){
            scanf("%d",&go[i][j]);
        }
    }
    for(int i=1;i<=k;i++){
        for(int j=0;j<l;j++){
            scanf("%d",&delay[i][j]);
        }
    }
    scanf("%d",&n);
}

const int ten[5]={1,10,100,1000,10000};
const int maxl=40;
struct Bignum{
    int d[maxl];
    Bignum(string s){
        int len=s.size();
        d[0]=(len-1)/5+1;
        int i,j,k;
        for(i=1;i<maxl;i++) d[i]=0;
        for(i=len-1;i>=0;i--){
            j=(len-i-1)/5+1;
            k=(len-i-1)%5;
            d[j]+=ten[k]*(s[i]-'0');
        }
        while(d[0]>1 && d[d[0]]==0) --d[0];
    }
    Bignum(){
        *this=Bignum(string("0"));
    }
    string toString(){
        string s("");
        int i,j,temp;
        for(i=4;i>=1;--i)if(d[d[0]]>=ten[i])break;
        temp=d[d[0]];
        for(j=i;j>=0;--j){
            s=s+(char)(temp/ten[j]+'0');
            temp%=ten[j];
        }
        for(i=d[0]-1;i>0;--i){
            temp=d[i];
            for(j=4;j>=0;--j){
                s=s+(char)(temp/ten[j]+'0');
                temp%=ten[j];
            }
        }
        return s;
    }
};
Bignum operator + (const Bignum &a,const Bignum &b){
    Bignum c;
    c.d[0]=max(a.d[0],b.d[0]);
    int i,x=0;
    for(i=1;i<=c.d[0];++i){
        x=a.d[i]+b.d[i]+x;
        c.d[i]=x%100000;
        x/=100000;
    }
    while(x){
        c.d[++c.d[0]]=x%100000;
        x/=100000;
    }
    return c;
}
Bignum dp[70][1100];
int vis[70][1100],marked;
Bignum DP(int ceng,int sta){
    if(ceng>=n){
        if(end[sta]) return Bignum("1");
        else return Bignum("0");
    }
    if(vis[ceng][sta]==marked) return dp[ceng][sta];
    Bignum ans=Bignum("0");
    for(int i=0;i<l;i++){
        if(tmp[sta][i]==-1) continue;
        ans=ans+DP(ceng+1,tmp[sta][i]);
    }
    vis[ceng][sta]=marked;
    return dp[ceng][sta]=ans;
}

int dfs(int st,int ch){
    if(tmp[st][ch]!=-2) return tmp[st][ch];
    int ans=-1;
    if(!delay[st][ch]) ans=go[st][ch];
    else{
        tmp[st][ch]=-1;
        ans=dfs(go[st][ch],ch);
    }
    return tmp[st][ch]=ans;
}

void init_go(){
    for(int st=0;st<=k;st++)
    for(int ch=0;ch<=l;ch++)
      tmp[st][ch]=-2;
    for(int st=1;st<=k;st++){
        for(int ch=0;ch<l;ch++){
            tmp[st][ch]=dfs(st,ch);
        }
    }
}
void solve(){
    init_go();
    marked++;
    Bignum ans=DP(0,S);
    printf("%s\n",ans.toString().c_str());
}

int main(){
    while(~scanf("%s",str)){
        init();
        read();
        solve();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值