BUPT 652 Confusing Problem(AC自动机+数位DP)
2012-10-09 21:59
357 查看
转载请注明出处,谢谢/article/2566293.html
by---cxlove
给出一个区间,问这个区间内有多少个数不包含数字0,而且至少出现了一次A或者B
http://acm.bupt.edu.cn/onlinejudge/newoj/showProblem/show_problem.php?problem_id=652
由于模式串只有两个,A,B其实可以直接匹配搞定吧,虽然我不会
还是老实用AC+数位DP吧,昨天做了ZOJ的BCD CODE,打算趁热把这题做了,结果跪了好久,哭~~~
自己对于数位DP理解不够,还有记忆化搜索
感觉数位DP的细节不好处理,比如说前导0,上下界之类的,现在尤其感觉前导0的问题
由于这题不能出现0,所以还需要注意,但是高位可以为0,也就是可以有前导0???
一直纠结于记忆化的问题,结果还是得用4维,dp[i][j][k][l]表示长度为i,当前在自动机的j结点,k表示是否高位全为0,l表示是否出现了指定串
by---cxlove
给出一个区间,问这个区间内有多少个数不包含数字0,而且至少出现了一次A或者B
http://acm.bupt.edu.cn/onlinejudge/newoj/showProblem/show_problem.php?problem_id=652
由于模式串只有两个,A,B其实可以直接匹配搞定吧,虽然我不会
还是老实用AC+数位DP吧,昨天做了ZOJ的BCD CODE,打算趁热把这题做了,结果跪了好久,哭~~~
自己对于数位DP理解不够,还有记忆化搜索
感觉数位DP的细节不好处理,比如说前导0,上下界之类的,现在尤其感觉前导0的问题
由于这题不能出现0,所以还需要注意,但是高位可以为0,也就是可以有前导0???
一直纠结于记忆化的问题,结果还是得用4维,dp[i][j][k][l]表示长度为i,当前在自动机的j结点,k表示是否高位全为0,l表示是否出现了指定串
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #include<string> #include<queue> #define inf 1<<30 #define M 60005 #define N 10005 #define maxn 300005 #define eps 1e-10 #define zero(a) fabs(a)<eps #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mem(a,b) memset(a,b,sizeof(a)) #define LL long long #define lson step<<1 #define rson step<<1|1 #define MOD 1000000009 using namespace std; struct Trie { Trie *next[10]; Trie *fail; int isword,kind; }; Trie *que[M],s[M]; int idx; Trie *NewNode() { Trie *tmp=&s[idx]; mem(tmp->next,NULL); tmp->isword=0; tmp->fail=NULL; tmp->kind=idx++; return tmp; } void Insert(Trie *root,char *s,int len) { Trie *p=root; for(int i=0; i<len; i++) { if(p->next[s[i]-'0']==NULL) p->next[s[i]-'0']=NewNode(); p=p->next[s[i]-'0']; } p->isword=1; } void Bulid_fail(Trie *root) { int head=0,tail=0; que[tail++]=root; root->fail=NULL; while(head<tail) { Trie *tmp=que[head++]; for(int i=0; i<10; i++) { if(tmp->next[i]) { if(tmp==root) tmp->next[i]->fail=root; else { Trie *p=tmp->fail; while(p!=NULL) { if(p->next[i]) { tmp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) tmp->next[i]->fail=root; } if(tmp->next[i]->fail->isword) tmp->next[i]->isword=tmp->next[i]->fail->isword; que[tail++]=tmp->next[i]; } else if(tmp==root) tmp->next[i]=root; else tmp->next[i]=tmp->fail->next[i]; } } } char str[100]; LL L,R; LL dp[20][55][2][2]; int bit[25],length,n; LL dfs(int len,int pos,int flag,int zero,bool limit) { if(len<=0) return flag==1; if(!limit&&flag&&dp[len][pos][zero][1]!=-1) return dp[len][pos][zero][1]; if(!limit&&!flag&&dp[len][pos][zero][0]!=-1) return dp[len][pos][zero][0]; LL ans=0; int up=limit?bit[len]:9; if(zero&&len>1) ans+=dfs(len-1,0,0,1,0==up); for(int i=1;i<=up;i++) { ans+=dfs(len-1,s[pos].next[i]->kind,flag||(s[pos].next[i]->isword),0,limit&&(i==up)); } if(!limit) { dp[len][pos][zero][flag]=ans; } return ans; } LL slove(LL num) { length=0; while(num) { bit[++length]=num%10; num/=10; } mem(dp,-1); return dfs(length,0,0,1,true); } int main() { int t; freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%d",&t); while(t--) { idx=0;Trie *root=NewNode(); scanf("%lld%lld",&L,&R); scanf("%s",str); Insert(root,str,strlen(str)); scanf("%s",str); Insert(root,str,strlen(str)); Bulid_fail(root); printf("%lld\n",slove(R)-slove(L-1)); } return 0; }
相关文章推荐
- zoj 3494 BCD Code (ac自动机+数位dp)
- [AC自动机+数位dp] zoj 3494 BCD Code
- ZOJ 3494 BCD Code (AC自动机+数位DP)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- zoj3494 BCD Code(AC自动机+数位dp)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- zoj 3494 BCD Code (ac自动机+数位dp)
- ZOJ 3494 (AC自动机+数位DP)
- ZOJ - 3494 BCD Code(AC自动机+数位DP)
- bzoj 3530: [Sdoi2014]数数 (AC自动机+数位DP)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- 【AC自动机+数位DP】SDOI2014 数数
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- 【bzoj3530】【sdoi2014】【数数】【AC自动机+数位dp】
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位DP)
- ZOJ 3494 (AC自动机+高精度数位DP)
- 5332. 【NOIP2017提高A组模拟8.23】密码 AC自动机+数位DP
- hdu 4518 【AC自动机+数位DP+二分】
- [BZOJ3530][Sdoi2014]数数(AC自动机上数位DP)