我们显然可以用字典树来维护这个东西,然后上面跑树形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; }