2 7 2 love ever 5 5 5 1 ab 5
lovever abab
每个串有个值,如果一个串中包含它就加上这个值,输出一个长度不超过N的串,使值最大。长度小的优先,长度一样时字典序小的优先。
dp[i][u]表示长度为i在节点u的最大值,s[i][u]表示这个最大值对应的串。初始dp[0][0]为0,其它都是-1(因为不是任意的dp[i][u]都能达到)。更新的时候如果dp值相等再判断当前串是否更优,直接strcmp就行了,这么简单粗暴我还WA了好几次。。
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> #include<queue> using namespace std; typedef unsigned long long ULL; const int MAXN=13; const int MAXM=110; const int MAXL=55; const int MAXNODE=MAXN*MAXM; const int LOGMAXN=50; const int INF=0x3f3f3f3f; const int SIGMA_SIZE=26; const int MOD=20090717; int T,N,M; int dp[MAXL][MAXNODE]; char s[MAXL][MAXNODE][MAXL]; struct AC{ int ch[MAXNODE][SIGMA_SIZE]; int val[MAXNODE]; int f[MAXNODE]; int sz; void clear(){ memset(ch[0],0,sizeof(ch[0])); val[0]=0; sz=1; } int idx(char c){ return c-'a'; } void insert(char* s,int v){ int u=0; for(int i=0;s[i];i++){ int c=idx(s[i]); if(!ch[u][c]){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; } void get_fail(){ queue<int> q; f[0]=0; for(int c=0;c<SIGMA_SIZE;c++){ int u=ch[0][c]; if(u){ f[u]=0; q.push(u); } } while(!q.empty()){ int r=q.front(); q.pop(); for(int c=0;c<SIGMA_SIZE;c++){ int u=ch[r][c]; if(!u){ ch[r][c]=ch[f[r]][c]; continue; } q.push(u); f[u]=ch[f[r]][c]; val[u]+=val[f[u]]; } } } }ac; void DP(){ int MAX=0; char ans[MAXL],tmp[MAXL]; memset(dp,-1,sizeof(dp)); dp[0][0]=0; ans[0]=0; s[0][0][0]=0; for(int i=0;i<N;i++) for(int u=0;u<ac.sz;u++) if(dp[i][u]!=-1){ strcpy(tmp,s[i][u]); int l=strlen(s[i][u]); for(int c=0;c<SIGMA_SIZE;c++){ tmp[l]=c+'a'; tmp[l+1]=0; if(dp[i][u]+ac.val[ac.ch[u][c]]>dp[i+1][ac.ch[u][c]]||dp[i][u]+ac.val[ac.ch[u][c]]==dp[i+1][ac.ch[u][c]]&&strcmp(tmp,s[i+1][ac.ch[u][c]])<0){ dp[i+1][ac.ch[u][c]]=dp[i][u]+ac.val[ac.ch[u][c]]; strcpy(s[i+1][ac.ch[u][c]],tmp); } if(dp[i+1][ac.ch[u][c]]>MAX||dp[i+1][ac.ch[u][c]]==MAX&&strlen(s[i+1][ac.ch[u][c]])<=strlen(ans)&&strcmp(s[i+1][ac.ch[u][c]],ans)<0){ MAX=dp[i+1][ac.ch[u][c]]; strcpy(ans,s[i+1][ac.ch[u][c]]); } } } printf("%s\n",ans); } char str[MAXM][MAXN]; int main(){ freopen("in.txt","r",stdin); scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); ac.clear(); for(int i=0;i<M;i++) scanf("%s",str[i]); int cnt; for(int i=0;i<M;i++){ scanf("%d",&cnt); ac.insert(str[i],cnt); } ac.get_fail(); DP(); } return 0; }