题目链接:Ring
解析:m个有价值的串,字符串s在字符串str中的价值 = s在str中出现的次数 × s的价值。问价值最大的长度为n的串是什么。
本题需要输出字典序最小的
在DP的时候开一个数组记录结果即可。
AC代码:
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int a[110];
int dp[55][1110];
char str[55][1110][55];
bool cmp(char s1[], char s2[]){
int len1 = strlen(s1);
int len2 = strlen(s2);
if(len1 != len2) return len1 < len2;
else return strcmp(s1, s2) < 0;
}
const int INF = 0x3f3f3f3f;
struct Trie{
int next[1110][26], fail[1110], end[1110];
int root, L;
int newnode(){
for(int i=0; i<26; i++) next[L][i] = -1;
end[L++] = -1;
return L-1;
}
void init(){
L = 0;
root = newnode();
}
void insert(char buf[], int id){
int len = strlen(buf);
int now = root;
for(int i=0; i<len; i++){
if(next[now][buf[i] - 'a'] == -1)
next[now][buf[i] - 'a'] = newnode();
now = next[now][buf[i] - 'a'];
}
end[now] = id;
}
void build(){
queue<int> Q;
fail[root] = root;
for(int i=0; i<26; i++){
if(next[root][i] == -1)
next[root][i] = root;
else{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while(!Q.empty()){
int now = Q.front();
Q.pop();
for(int i=0; i<26; i++){
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
int solve(int n){
for(int i=0; i<=n; i++)
for(int j=0; j<L; j++)
dp[i][j] = -INF;
dp[0][0] = 0;
strcpy(str[0][0], "");
char ans[55];
strcpy(ans, "");
int Max = 0;
char tmp[55];
for(int i=0; i<n; i++)
for(int j=0; j<L; j++)
if(dp[i][j] >= 0){
strcpy(tmp, str[i][j]);
int len = strlen(tmp);
for(int k=0; k<26; k++){
int nxt = next[j][k];
tmp[len] = 'a' + k;
tmp[len+1] = 0;
int tt = dp[i][j];
if(end[nxt] != -1) tt += a[ end[nxt] ];
if(dp[i+1][nxt] < tt || (dp[i+1][nxt] == tt && cmp(tmp, str[i+1][nxt]))){
dp[i+1][nxt] = tt;
strcpy(str[i+1][nxt], tmp);
if(tt > Max || (tt == Max && cmp(tmp, ans))){
Max = tt;
strcpy(ans, tmp);
}
}
}
}
printf("%s\n", ans);
}
};
char buf[60];
Trie ac;
int main(){
// freopen("in.txt", "r", stdin);
int T;
int n, m;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
ac.init();
for(int i=0; i<m; i++){
scanf("%s", buf);
ac.insert(buf, i);
}
for(int i=0; i<m; i++)
scanf("%d", &a[i]);
ac.build();
ac.solve(n);
}
return 0;
}