题目链接: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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-24 22:36:55