hdu 2296 AC自动机+DP+路径字符串记录(较麻烦)
题意:给出n个字符串,以及每个字符串的权值,求权值最大,字符串长度不超过m,最短且字典序最小的字符串。
//#pragma comment(linker, "/STACK:102400000") #include<cstdlib> #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<map> #include<list> #include<queue> #include<stack> #include<vector> #define tree int o,int l,int r #define lson o<<1,l,mid #define rson o<<1|1,mid+1,r #define lo o<<1 #define ro o<<1|1 #define pb push_back #define mp make_pair #define ULL unsigned long long #define LL long long #define inf 0x7fffffff #define eps 1e-7 #define N 1009 #define M 26 using namespace std; int m,n,T,t,x,y,u; int ch[N][M],v[N],sz; int f[N],last[N]; char str[109][15]; int d[N][55],pre[N][55],len[N][55]; void init() { sz=1; memset(ch[0],0,sizeof(ch[0])); memset(v,0,sizeof(v)); memset(last,0,sizeof(last)); memset(d,-1,sizeof(d)); memset(len,0,sizeof(len)); } int idx(char c) { return c-'a'; } void insert(char str[],int val) { int u=0; for(int i=0; str[i]; i++) { int c=idx(str[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); ch[u][c]=sz++; } u=ch[u][c]; } v[u]+=val; } void getac() { f[0]=0; queue<int>q; for(int c=0; c<M; c++) { int u=ch[0][c]; if(u) { f[u]=0; q.push(u); last[u]=v[u];///////////// } } while(!q.empty()) { int r=q.front(); q.pop(); for(int c=0; c<M; c++) { int u=ch[r][c]; if(!u) { ch[r][c]=ch[f[r]][c]; } else { q.push(u); int s=f[r]; f[u]=ch[s][c]; last[u]=v[u]+last[f[u]];////// } } } } int dp(int u,int sub) { if(sub==n)return 0; int &ans=d[u][sub]; if(ans!=-1)return ans; ans=0; for(int i=0; i<M; i++) { int c=ch[u][i]; if(last[c]+dp(c,sub+1)>ans)//先保证值最大 { ans=max(ans,last[c]+dp(c,sub+1)); pre[u][sub]=i; if(ans>0) len[u][sub]=len[c][sub+1]+1; } else if (last[c]+dp(c,sub+1)==ans&&len[u][sub]>len[c][sub+1]+1)//再保证长度最短 { pre[u][sub]=i; if(ans>0) len[u][sub]=len[c][sub+1]+1; } } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("ex.in","r",stdin); #endif int ncase=0; scanf("%d",&T); while(T--) { init(); scanf("%d%d",&n,&m); for(int i=0; i<m; ++i) scanf("%s",str[i]); for(int i=0; i<m; ++i) { scanf("%d",&t); insert(str[i],t); } getac(); dp(0,0); int u=0,i=0; while(d[u][i]>0) { printf("%c",pre[u][i]+'a'); u=ch[u][pre[u][i]]; i++; } puts(""); } return 0; }