题解 P2462 [SDOI2007]游戏

link

这个题挺简单。

显然只有字符串的每种字母个数才有意义,哈希表浅存一下。

对于每个字符串,枚举 26 个字母,连一条向添加该字母后的字符串的边,显然最后会建出一个 DAG,找这个图的最长路即可,这个复杂度比较对,O(nΣ),Σ=26

或者直接 DP,先按字符串长度排个序,每次转移找比自己长度少一的字符串,判一下能否转移即可,这个复杂度很假 O(n2Σ),但常数小,不过要卡肯定能卡(?)

#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;
}
posted @   Terac  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示