【Luogu3041】视频游戏的连击(AC自动机,动态规划)
生活随笔
收集整理的這篇文章主要介紹了
【Luogu3041】视频游戏的连击(AC自动机,动态规划)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題面鏈接
題解
首先構建出AC自動機
然后在AC自動機上面跑DP
轉移很顯然從Trie樹的節點跳到他的兒子節點
但是要注意一個問題,
在計算的時候,每一個節點加入后能夠
造成的貢獻
要加上他的子串的貢獻
至于DP:
設f[i][j]表示已經使用了i個字母
當前在Trie樹的第j個節點上面能夠產生的最大貢獻
很顯然,轉移到他的兒子節點上面,同時統計貢獻即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
#define INF 1000000
int N,K;
int tot=0,ans;
char s[20];
int f[1100][400];
struct Node
{int vis[3];int p;int fail;
}t[5000];
void Add(char *s)
{int l=strlen(s);int now=0;for(int i=0;i<l;++i){if(!t[now].vis[s[i]-'A'])t[now].vis[s[i]-'A']=++tot;now=t[now].vis[s[i]-'A'];}t[now].p++;
}
void Build()
{queue<int> Q;for(int i=0;i<3;++i)if(t[0].vis[i])Q.push(t[0].vis[i]);while(!Q.empty()){int u=Q.front();Q.pop();for(int i=0;i<3;++i){if(t[u].vis[i]){t[t[u].vis[i]].fail=t[t[u].fail].vis[i];Q.push(t[u].vis[i]);}elset[u].vis[i]=t[t[u].fail].vis[i];}t[u].p+=t[t[u].fail].p;}
}
void DP()
{for(int T=0;T<=K;++T)for(int i=1;i<=tot;++i)f[T][i]=-INF;for(int T=1;T<=K;++T)for(int i=0;i<=tot;++i)for(int j=0;j<3;++j)f[T][t[i].vis[j]]=max(f[T][t[i].vis[j]],f[T-1][i]+t[t[i].vis[j]].p);for(int i=0;i<=tot;++i)ans=max(ans,f[K][i]);
}
int main()
{scanf("%d%d",&N,&K);for(int i=1;i<=N;++i){scanf("%s",s);Add(s);}Build();DP();printf("%d\n",ans);return 0;
}
轉載于:https://www.cnblogs.com/cjyyb/p/7647485.html
總結
以上是生活随笔為你收集整理的【Luogu3041】视频游戏的连击(AC自动机,动态规划)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鼻子手术要多少钱
- 下一篇: ntpdate[31915]: the