转载请注明出处,谢谢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; }