Ring HDU - 2296 AC自动机DP路径记录
构造n长串,若含有模板串x可获得a[x]的价值,同价值取字典序最小,输出路径
dp[i][j]表示长度i转移态j的最大价值,对应一个path[i][j]记录路径
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=1e6+7; const long long mod=1e9+7; const int sigma=26; ll ans; int a[110]; int dp[55][1111]; //串长i匹配到j位置最大价值 string path[55][1111]; //路径 struct automata{ int ch[maxn][sigma]; int val[maxn]; int f[maxn]; int sz; int newnode(){ memset(ch[sz],0,sizeof(ch[sz])); f[sz]=val[sz]=0; return sz++; } void init(){ memset(val,0,sizeof(val)); sz=0; newnode(); } void insert(char *s,int v){ int u=0; int len=strlen(s); for(int i=0;i<len;i++){ int id=s[i]-'a'; if(!ch[u][id])ch[u][id]=newnode(); u=ch[u][id]; } val[u]=v; } void solve(int n){ memset(dp,-1,sizeof dp); dp[0][0]=0;path[0][0]=""; for(int i=0;i<n;i++){ for(int j=0;j<sz;j++){ if(dp[i][j]!=-1){ //可达,更新后继 for(int k=0;k<26;k++){ int u=ch[j][k]; if(dp[i][j]+a[val[u]] > dp[i+1][u]){ dp[i+1][u]=dp[i][j]+a[val[u]]; path[i+1][u]=path[i][j]+(char)(k+'a'); continue; } if(dp[i][j]+a[val[u]]==dp[i+1][u]){ string str=path[i][j]; str.pb(k+'a'); if(str<path[i+1][u])path[i+1][u]=str; } } } } } int ans=0,row; string str; for(int i=0;i<=n;i++) for(int j=0;j<sz;j++) if(ans<dp[i][j]){ ans=dp[i][j];row=i; } if(ans==0){printf("\n");return;} str=""; for(int j=0;j<sz;j++){ if(dp[row][j] == ans && (str>path[row][j]||str=="")) str=path[row][j]; } cout<<str<<endl; } void build(){ queue<int>q; q.push(0); while(!q.empty()){ int u=q.front();q.pop(); if(val[f[u]]){ //val[u]=(val[u]+val[f[u]]; a[val[u]]+=a[val[f[u]]]; } for(int i=0;i<sigma;i++){ int v=ch[u][i]; if(!v)ch[u][i]=ch[f[u]][i]; else q.push(v); if(u&&v)f[v]=ch[f[u]][i]; } } } }ac; char buf[60]; int n,m; int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); ac.init(); for(int i=1;i<=m;i++){ scanf("%s",buf); ac.insert(buf,i); } for(int i=1;i<=m;i++)scanf("%d",&a[i]); ac.build();ac.solve(n); } }