ZSOI2012 撿金子 字典樹+樹形DP

我們顯然可以用字典樹來維護這個東西,然後上面跑樹形DP

唯一比較虛的是動態的字典樹就有三個點超時= =靜態的就跑的超快了

代碼中含有靜態的動態的代碼

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define efo(i,x) for(int i=last[x];i!=0;i=e[i].next)
using namespace std;
inline LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 50005
#define M 12
#define K 27
#define L 55
#define sonmax 26
int n=0,m,nm;
int fa[N];
int f[N][M];
struct edge
{
	int y,next;
}e[N*2];
int last[N],ne=0;
struct st
{
	int len;
	char s[L];
}a[N];
struct sor
{
	int a,b;
}b[N];

bool strcom(sor a,sor b)
{
	return a.b<b.b;
}

void add(int x,int y)
{
//	cout<<x<<' '<<y<<endl;
	e[++ne].y=y;e[ne].next=last[x];last[x]=ne;
}

//the dynamic trie is too slow
/*
typedef struct node
{
	int num;
	int xu;
	bool terminal;
	struct node * next[sonmax];
}*trie,node;
trie root;
void init_trie(trie &p)
{
	p=(trie)malloc(sizeof(node));
	for(int i=0;i<26;i++)p->next[i]=0;
	p->terminal=0;
	p->num=0;
}
void insert(trie p,char str[])
{
	int i=0,cnt=0;
	while(str[i]!='\0')
	{
		if(!p->next[str[i]-'A'])
		{
			trie q;
			init_trie(q);
			p->next[str[i]-'A']=q;
		}
		p=p->next[str[i]-'A'];
		p->num++;
		if(p->terminal)cnt=p->xu;
		i++;
	}
	if(p->terminal)cout<<"STOP!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
	p->terminal=1;
	p->xu=++n;
	add(cnt,n);
	fa[n]=cnt;
}
*/
//set the static trie
typedef struct node
{
	int xu;
	bool terminal;
	int next[26];
	void clear()
	{
		terminal=0;
		xu=0;
		memset(next,0,sizeof(next));
	}
}Trietree;
Trietree trie[1200000];
int xu=0;
void insert(char str[])
{
	int i=0,cnt=0,k=0;
	while(str[i]!='\0')
	{
		if(trie[k].next[str[i]-'A']==0)
		{
			xu++;
			trie[xu].clear();
			trie[k].next[str[i]-'A']=xu;
		}
		k=trie[k].next[str[i]-'A'];
		if(trie[k].terminal==1)cnt=trie[k].xu;
		i++;
	}
	trie[k].terminal=1;
	trie[k].xu=++n;
	add(cnt,n);
	fa[n]=cnt;
}

void dfs(int x)
{
	fo(i,0,nm)f[x][i]=0;
	efo(i,x)
	{
		dfs(e[i].y);
		fd(j,nm,1)
		{
			fo(k,1,j)
				f[x][j]=max(f[x][j],f[x][j-k]+f[e[i].y][k]);
		}
	}
	if(x!=0)fo(i,1,nm)f[x][i]++;f[x][0]=0;
//	cout<<"DP:"<<x<<' '<<f[x][1]<<' '<<f[x][2]<<endl;
}

int main()
{
	double tt=clock();
	freopen("gold.in","r",stdin);
	freopen("gold.out","w",stdout);
//	init_trie(root);
	trie[0].clear();
	m=read(),read(),read(),nm=read();
	fo(i,1,m)
	{
		scanf("%s",a[i].s);
		a[i].len=strlen(a[i].s);
		b[i].a=i;b[i].b=a[i].len;
//		insert(root,s);
	}
	sort(b+1,b+m+1,strcom);
	fo(i,1,m)
	{
		insert(a[b[i].a].s);
//		insert(root,a[b[i].a].s);
//		cout<<i<<' '<<a[b[i].a].s<<endl;
	}
	dfs(0);
	int ans=0;
	fo(i,1,nm)ans=max(ans,f[0][i]);
	cout<<ans<<endl;
	printf("%lf\n",clock()-tt);
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章