Ring HDU

题意:

就是现在给出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 }
View Code
原文地址:https://www.cnblogs.com/qldabiaoge/p/11379243.html