题解 P2462 [SDOI2007]游戏
这个题挺简单。
显然只有字符串的每种字母个数才有意义,哈希表浅存一下。
对于每个字符串,枚举 $26$ 个字母,连一条向添加该字母后的字符串的边,显然最后会建出一个 DAG,找这个图的最长路即可,这个复杂度比较对,$O(n\Sigma),\Sigma = 26$。
或者直接 DP,先按字符串长度排个序,每次转移找比自己长度少一的字符串,判一下能否转移即可,这个复杂度很假 $O(n^2\Sigma)$,但常数小,不过要卡肯定能卡(?)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10, M = 1e2 + 10;
int n, ans, anss, dp[N], pre[N], ps[M], pt[M];
struct node {
char s[M];
int cnt[26], len;
} a[N];
bool cmp(node a, node b) { return a.len < b.len; }
int main() {
while(~scanf("%s", a[++n].s + 1))
a[n].len = strlen(a[n].s + 1);
--n;
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= a[i].len; j++)
a[i].cnt[a[i].s[j] - 'a']++;
for(int i = 1; i <= n; i++)
if(a[i].len != a[i - 1].len) ps[a[i].len] = pt[a[i].len] = i;
else pt[a[i].len] = i;
for(int i = 1; i <= n; i++) {
for(int j = ps[a[i].len - 1]; j && j <= pt[a[i].len - 1]; j++) {
bool flg = 0;
for(int k = 0; k < 26; k++)
if(a[j].cnt[k] > a[i].cnt[k]) {
flg = 1;
break;
}
if(!flg)
if(dp[i] < dp[j]) {
dp[i] = dp[j];
pre[i] = j;
}
}
dp[i]++;
if(ans < dp[i])
ans = dp[i], anss = i;
}
printf("%d\n", ans);
stack<int> st;
for(int i = anss; i; i = pre[i])
st.push(i);
while(!st.empty())
printf("%s\n", a[st.top()].s + 1), st.pop();
return 0;
}

浙公网安备 33010602011771号