题意:
就是现在给出m个串,每个串都有一个权值,现在你要找到一个长度不超过n的字符串,
其中之前的m个串每出现一次就算一次那个字符串的权值,
求能找到的最大权值的字符串,如果存在多个解,输出最短的字典序最小的串。
当最大全权值为0时输出空串。
输入最多100个子串,权值为不超过100的正整数。
每个子串长度至少为1,不超过10, n <= 50
如果不考虑方案输出,这题就变得相当简单了。
dp【i】【j】表示走到长度为 i 的时候 ,到AC自动机 j 这个节点所获得的最大权值和。
我一开始的做法是在dp的过程中获得那个最优方案。
最后死活过不去,就换了一种超级暴力的写法。
将所有情况保存下来,去一个个找字典序最小的方案。
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <time.h> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 14 #define pi acos(-1.0) 15 #define eps 1e-9 16 #define fi first 17 #define se second 18 #define rtl rt<<1 19 #define rtr rt<<1|1 20 #define bug printf("****** ") 21 #define mem(a, b) memset(a,b,sizeof(a)) 22 #define name2str(x) #x 23 #define fuck(x) cout<<#x" = "<<x<<endl 24 #define sf(n) scanf("%d", &n) 25 #define sff(a, b) scanf("%d %d", &a, &b) 26 #define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c) 27 #define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d) 28 #define pf printf 29 #define FIN freopen("../date.txt","r",stdin) 30 #define gcd(a, b) __gcd(a,b) 31 #define lowbit(x) x&-x 32 #define IO iOS::sync_with_stdio(false) 33 34 35 using namespace std; 36 typedef long long LL; 37 typedef unsigned long long ULL; 38 const int maxn = 1e6 + 7; 39 const int maxm = 8e6 + 10; 40 const int INF = 0x3f3f3f3f; 41 const int mod = 20090717; 42 43 44 char str[105][12]; 45 int n, m, cost[105]; 46 47 48 struct Aho_Corasick { 49 int next[1010][26], fail[1010], End[1010]; 50 int root, cnt; 51 52 int newnode() { 53 for (int i = 0; i < 26; i++) next[cnt][i] = -1; 54 End[cnt++] = 0; 55 return cnt - 1; 56 } 57 58 void init() { 59 cnt = 0; 60 root = newnode(); 61 } 62 63 void insert(char buf[], int id) { 64 int len = strlen(buf); 65 int now = root; 66 for (int i = 0; i < len; i++) { 67 if (next[now][buf[i] - 'a'] == -1) next[now][buf[i] - 'a'] = newnode(); 68 now = next[now][buf[i] - 'a']; 69 } 70 End[now] += id; 71 } 72 73 void build() { 74 queue<int> Q; 75 fail[root] = root; 76 for (int i = 0; i < 26; i++) 77 if (next[root][i] == -1) next[root][i] = root; 78 else { 79 fail[next[root][i]] = root; 80 Q.push(next[root][i]); 81 } 82 while (!Q.empty()) { 83 int now = Q.front(); 84 Q.pop(); 85 End[now] += End[fail[now]]; 86 for (int i = 0; i < 26; i++) 87 if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; 88 else { 89 fail[next[now][i]] = next[fail[now]][i]; 90 Q.push(next[now][i]); 91 } 92 } 93 } 94 95 void debug() { 96 for (int i = 0; i < cnt; i++) { 97 printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]); 98 for (int j = 0; j < 26; j++) printf("%2d", next[i][j]); 99 printf("] "); 100 } 101 } 102 } ac; 103 104 int dp[55][1010]; 105 string path[55][1010]; 106 107 int main() { 108 // FIN; 109 int T; 110 sf(T); 111 while (T--) { 112 sff(n, m); 113 for (int i = 0; i < m; ++i) scanf("%s", str[i]); 114 for (int i = 0; i < m; i++) sf(cost[i]); 115 ac.init(); 116 for (int i = 0; i < m; ++i) ac.insert(str[i], cost[i]); 117 ac.build(); 118 mem(dp, -1); 119 for (int i = 0; i <= n; i++) 120 for (int j = 0; j < ac.cnt; j++) 121 path[i][j] = ""; 122 int ans = 0, num1 = 0, num2 = 0; 123 dp[0][0] = 0; 124 for (int i = 0; i < n; ++i) { 125 for (int j = 0; j < ac.cnt; ++j) { 126 if (dp[i][j] == -1) continue; 127 for (int k = 0; k < 26; ++k) { 128 int idx = ac.next[j][k]; 129 if (dp[i + 1][idx] < dp[i][j] + ac.End[idx]) { 130 dp[i + 1][idx] = dp[i][j] + ac.End[idx]; 131 path[i + 1][idx] = path[i][j] + char(k + 'a'); 132 } else if (dp[i + 1][idx] == dp[i][j] + ac.End[idx] && 133 path[i + 1][idx] > path[i][j] + char(k + 'a')) { 134 //fuck(path[i][j]); 135 path[i + 1][idx] = path[i][j] + char(k + 'a'); 136 // fuck(path[i][j]); 137 138 } 139 } 140 } 141 } 142 for (int i = 1; i <= n; i++) { 143 for (int j = 0; j < ac.cnt; ++j) { 144 if (ans < dp[i][j]) { 145 ans = dp[i][j], num1 = i, num2 = j; 146 } else if (ans == dp[i][j]&&path[num1][num2] > path[i][j] && path[num1][num2].size()>=path[i][j].size()) { 147 num1 = i, num2 = j; 148 } 149 } 150 } 151 // printf("%d ", ans); 152 cout << path[num1][num2] << endl; 153 } 154 return 0; 155 }