有一種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已經不能表示解碼之後的字元,要用 ...