zoukankan      html  css  js  c++  java
  • CodeForces

    题目链接

    题目大意

      给你n个字符串,让你求一个集合,这些集合里的字符串是n个字符串中某些字符串的前缀,并且集合中的字符串任意两个都不相似,相似的定义为其中一个字符串去掉第一个字符和另一个完全相同。

    解题思路

      在字典树上从根到每一个节点的简单路径都是某些字符串的一个前缀,和他相似的点就是fail指针指向的比当前点深度小1的点(因为fail指针的定义是与当前字符串的后缀能匹配的最大前缀长度,深度小1自然就只有第一个不匹配),没有相似的字符串即当前节点i与fail指针指向的结点fail[i]只能选择一个,根据fail指针建出fail树跑树形dp即可。

    代码

    const int maxn = 2e6+10;
    int tr[maxn][26], idx, dep[maxn];
    char str[maxn];
    vector<int> e[maxn];
    void insert() {
        int p = 0;
        for (int i = 0; str[i]; ++i) {
            int t = str[i]-'a';
            if (!tr[p][t]) tr[p][t] = ++idx, dep[idx] = dep[p]+1;
            p = tr[p][t];
        }
    }
    int q[maxn], fail[maxn];
    void build() {
        int tt = -1, hh = 0;
        for (int i = 0; i<26; ++i)
            if (tr[0][i]) q[++tt] = tr[0][i];
        while(hh<=tt) {
            int t = q[hh++];
            for (int i = 0; i<26; ++i) {
                int p = tr[t][i];
                if (!p) tr[t][i] = tr[fail[t]][i];
                else {
                    fail[p] = tr[fail[t]][i];
                    q[++tt] = p;
                }
            }
        }
        for (int i = 0; i<=idx; ++i) clr(tr[i], 0);
    }
    int dp[maxn][2];
    void dfs(int u) {
        //cout << u << endl;
        dp[u][0] = 0, dp[u][1] = 1;
        for (auto v : e[u]) {
            dfs(v);
            dp[u][0] += max(dp[v][0], dp[v][1]);
            dp[u][1] += dp[v][0];
        }
    }
    int main() {
        IOS;
        int __; cin >> __;
        while(__--) {
            idx = 0;
            int n; cin >> n;
            for (int i = 1; i<=n; ++i) {
                cin >> str;
                insert();
            }
            build();
            for (int i = 1; i<=idx; ++i) {
                if (dep[i]==dep[fail[i]]+1) e[fail[i]].push_back(i);
                else e[0].push_back(i);
            }
            dfs(0);
            for (int i = 0; i<=idx; ++i) e[i].clear(), dep[i] = 0, fail[i] = 0;
            cout << dp[0][0] << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    altium designer 工程中的原理图库和封装如何提取出来
    555是集成电路
    安装JDK+Tomcat,进行环境变量设置,和运行JSP
    2018年房价会涨吗?
    MySQLroot密码的恢复方法
    mysql中的数据类型长度
    感觉还不错,受益很高,有保障
    phpstorm问题
    Mac上的抓包工具Charles
    解决Firefox显示“已阻止载入混合活动内容”的方法
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/15327444.html
Copyright © 2011-2022 走看看