ZOJ 3494 AC自動機 數字DP

2021-08-06 04:08:09 字數 1891 閱讀 5103

有一種bcd編碼方案,求a到b範圍內的數字的bcd編碼有多少個不包含不能包含的字串。

數字範圍這麼大,很明顯就能看出來是數字dp。基於ac自動機的數字dp使得數字dp容易了不少,因為ac自動機自帶狀態轉移。在數字dp選取每一位的時候,基於ac自動機狀態轉移一下,如果轉移到不能轉移的狀態,就直接返回-1。如果轉移到合法狀態,就繼續dfs。唯一需要注意的就是需要大整數的減法,不過隨便寫寫就行了,有前導0也無所謂,反正不影響數字dp。

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define up(i,l,h) for(int i=l;i#define down(i,h,l) for(int i=h-1;i>=l;i--)

#define w(a) while(a)

#define mem(a,b) memset(a,b,sizeof(a))

#define inf 0x3f3f3f3f

#define ll long long

#define maxn 100010

#define mod 1000000009

#define eps 1e-10

#define int ll

using

namespace

std;

int ch[2010][10];

int sz;

int val[2010],f[2010];

char st[30];

int dig[220];

int dp[210][2010];

char a[210],b[210];

int code[10][4]= ,,,,,,,,,};

int run(int u,int x)

up(i,0,4)

}return u;

}void insert()

u=ch[u][x];

}val[u]=1;

// cout<<"u"<}

void getfail()

}w(!q.empty())

q.push(u);

int v=f[r];

f[u]=ch[v][i];

val[u]|=val[f[u]];

// cout<<"val"<}

}}int dfs(int len,int u,bool first,bool up)

if(!up&&!first&&(dp[len][u]!=-1))

int n=up?dig[len]:9;

int ans=0;

up(i,0,n+1) else

ans=(ans+dfs(len-1,temp,false,up&&i==n))%mod;}}

if(!up&&!first)

return ans%mod;

}int solve(char *x)

return dfs(len+1,0,true,true);

}main()

getfail();

scanf("%s%s",&a,&b);

int len=strlen(a);

down(i,len,0)else

}printf("%lld\n",(solve(b)-solve(a)+mod)%mod);

}}/*

5511001

1 10

*/

zoj3494 ac自動機 數字dp

題解 把給的串建ac自動機,然後得到的bcd i j bcd i j 表示在ac自動機上的狀態i,後面加入j會轉移的狀態,1表示不能加 然後數字dp,dp i j 表示取到第i位狀態為j後面的數字隨便取的方案數,這裡是記憶化。include include include include inclu...

ZOJ 3494 AC自動機 高精度數字DP

題目鏈結 題目大意 給定一些被禁止的bcd碼。問指定範圍內不含有任何這些禁止的bcd碼的數的個數。解題思路 ac自動機部分 首先insert這些被禁止的bcd碼。然後打一下自動機前後狀態的轉移的表,用bcd i j 表示自動機狀態i時,下乙個數字是j的自動機的下乙個狀態。一開始我考慮最先dfs的位在...

zoj3430 AC自動機模擬

jibancanyang author jibancanyang created time 五 5 6 16 14 59 2016 file name jy.cpp problem analyse 此題難就難在編碼,還有題意問的是病毒有多少種不是多少個,注意char已經不能表示解碼之後的字元,要用 ...