您的位置:首页 > 其它

CC FAVNUM (AC自动机+数位DP)

2012-11-23 19:33 274 查看
转载请注明出处,谢谢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]
[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: