轉載請註明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents
by---cxlove
xiaodao給的題目,第一次codechef,好高端的樣子。
給出一些模式串,包含至少一個模式串的為指定串。
問區間內第K個指定串。
把模式串加入到自動機中,然後可以求出區間內指定串的個數。
二分答案就行了
其實還是很水的。。。
準備準備跟著xiaodao學尾碼自動機了
#include<iostream>#include<cstdio>#include<map>#include<cstring>#include<cmath>#include<vector>#include<algorithm>#include<set>#include<string>#include<queue>#define inf 100000005#define M 20005#define N 2000#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 mp(a,b) make_pair(a,b)#define mem(a,b) memset(a,b,sizeof(a))#define LL long long#define MOD 1000000007#define lson step<<1#define rson step<<1|1#define sqr(a) ((a)*(a))#define Key_value ch[ch[root][1]][0]//#pragma comment(linker, "/STACK:1024000000,1024000000")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][N][2][2];int bit[25],length;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; for(int i=0; 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; } return dfs(length,0,0,1,true);}LL l,r,k;LL ans;int n;void Fuck(){ LL mid,tmp=slove(l-1); while(l<=r) { mid=(l+r)>>1; if(slove(mid)-tmp>=k) { r=mid-1; ans=mid; } else l=mid+1; }}int main(){ //freopen("1.in","r",stdin); while(scanf("%lld%lld%lld%d",&l,&r,&k,&n)!=EOF) { idx=0;mem(dp,-1); Trie *root=NewNode(); for(int i=0; i<n; i++) { scanf("%s",str); Insert(root,str,strlen(str)); } Bulid_fail(root); ans=-1; Fuck(); if(ans==-1) printf("no such number\n"); else printf("%lld\n",ans); } return 0;}