简单的AC自动机+DP,DP很容易想到。但是这题的输出实在是太恶心了。。。而且这题的数据很弱。。。我交了一发样例都没过的代码都AC了。。。后来把代码改了,自己弄的几组数据测了几下,感觉没什么太大的问题了。。
附一组数据:
1
5 4
s sd d fgf
2 6 4 10
答案是dsdsd。。。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 1005 #define eps 1e-6 #define mod 10007 #define INF 99999999 #define lowbit(x) ((x)&(-(x))) #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; char str[105][20]; int num[105]; struct trie { int next[maxn][26]; int fail[maxn]; int end[maxn]; int loc[maxn]; queue<int> q; int top, root, now; int newnode(void) { fail[top] = -1; end[top] = 0; for(int i = 0; i < 26; i++) next[top][i] = -1; return top++; } void init(void) { top = 0; root = newnode(); } void insert(char *s, int x) { int len = strlen(s), i, k; now = root; for(i = 0; i < len; i++) { k = s[i] - 'a'; if(next[now][k] == -1) next[now][k] = newnode(); now = next[now][k]; loc[now] = k; } end[now] = x; } void build(void) { now = root; for(int i = 0; i < 26; i++) { if(next[now][i] == -1) next[now][i] = root; else { fail[next[now][i]] = root; q.push(next[now][i]); } } while(!q.empty()) { now = q.front(); q.pop(); if(end[fail[now]]) end[now] += end[fail[now]]; 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]); } } } }tmp; int dp[105][maxn]; bool vis[105][maxn]; int loc[105][maxn]; string a[55][maxn]; char b[maxn]; int n, m; inline int cal(int i, int j) { return (i-1)*m+j; } void init(void) { memset(dp, 0, sizeof dp); memset(vis, 0, sizeof vis); memset(loc, 0, sizeof loc); for(int i = 0; i < 55; i++) for(int j = 0; j < maxn; j++) a[i][j].clear(); } void read(void) { int i; tmp.init(); scanf("%d%d", &n, &m); for(i = 0; i < m; i++) scanf("%s", str[i]); for(i = 0; i < m; i++) scanf("%d", &num[i]); for(i = 0; i < m; i++) tmp.insert(str[i], num[i]); tmp.build(); } void work(void) { int i, j, k, ans, res, tmpi, tmpj; vis[0][0] = true; for(i = 0; i < n; i++) for(j = 0; j < tmp.top; j++) if(vis[i][j]) for(k = 0; k < 26; k++) { b[0] = tmp.loc[tmp.next[j][k]]+'a'; b[1]='\0'; if(dp[i+1][tmp.next[j][k]] == dp[i][j] + tmp.end[tmp.next[j][k]] && loc[i+1][tmp.next[j][k]]) { if(a[i+1][tmp.next[j][k]] > a[i][j] + b) a[i+1][tmp.next[j][k]] = a[i][j] + b; vis[i+1][tmp.next[j][k]] = true; } if(dp[i+1][tmp.next[j][k]] < dp[i][j] + tmp.end[tmp.next[j][k]] || loc[i+1][tmp.next[j][k]] == 0) { loc[i+1][tmp.next[j][k]] = 1; a[i+1][tmp.next[j][k]] = a[i][j] + b; dp[i+1][tmp.next[j][k]] = dp[i][j] + tmp.end[tmp.next[j][k]]; vis[i+1][tmp.next[j][k]] = true; } } ans = 0; for(i = 0; i < tmp.top; i++) if(ans < dp[n][i]) ans = dp[n][i], res = i; tmpi = n, tmpj = res; if(ans == 0) { printf("\n"); return; } for(i = n; i >= 1; i--){ res = 0; for(j = 0; j < tmp.top; j++) { if(res < dp[i][j]) res = dp[i][j]; if(ans == dp[i][j]) { if(tmpi > i) tmpi = i, tmpj = j; else if(a[tmpi][tmpj] > a[i][j]) tmpi = i, tmpj = j; } } if(res != ans) break; } printf("%s\n", a[tmpi][tmpj].c_str()); } int main(void) { int _; while(scanf("%d", &_)!=EOF){ while(_--) { init(); read(); work(); } } return 0; }