zoukankan      html  css  js  c++  java
  • [20200722NOIP提高组模拟T4]词韵

    题目链接:

      P4471 [BJWC2018]词韵

     

    题目大意:

      懒得打了,自己看题吧.

    solution:

      由于本题求的是最长公共后缀,所以我们可以想到从末尾倒序构造trie,然后再来分析此题.可以注意到的是,两个词能够押韵,当且仅当它们的关键点在trie上是父子或兄弟关系.所以我们可以考虑树形DP.由于兄弟节点较难维护,所以我们可以在父节点中更新,所以我们只看其子节点.对于一个点$x$,f[x]维护该点的dp值,g[x]维护该点的子节点的子树中最大的连续关键点链值.单词$x$可以从前插入若干个单词,也可以从后插入若干个单词,构成一个押韵的序列,所以根据贪心策略,我们选择g[x]的最大值_和次大值__(没错,它们都是变量名),然后统计dp答案即可.

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #define R register
    #define next exntttttttttttttttt
    #define debug puts("mlg")
    using namespace std;
    typedef int ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writesp(ll x);
    inline void writeln(ll x);
    struct node{
        ll son[26],cnt;
    }trie[1000000];
    char wn;
    ll c[1000000],h;
    ll n,tot;
    inline void Insert(){
        ll now=0;
        for(;h;h--){
            now=trie[now].son[c[h]]?trie[now].son[c[h]]:(trie[now].son[c[h]]=++tot);
        }
        ++trie[now].cnt;
    }
    ll ans,f[1000000],g[1000000];
    inline void dfs(ll x){
        ll _=0,__=0;
        for(R ll i=0;i<26;i++){
            if(trie[x].son[i]){
                dfs(trie[x].son[i]);
                if(!trie[trie[x].son[i]].cnt) continue;
                f[x]+=trie[trie[x].son[i]].cnt;
                if(g[trie[x].son[i]]>_){
                    __=_;
                    _=g[trie[x].son[i]];
                }
                else if(g[trie[x].son[i]]>__) __=g[trie[x].son[i]];
            }
        }
        if(trie[x].cnt) g[x]=f[x]+_;
        ans=max(ans,_+__+f[x]+trie[x].cnt);
    }
    int main(){
        n=read();
        for(R ll i=1;i<=n;i++){
            while(wn<'a'||wn>'z') wn=getchar();
            h=0;
            while(wn>='a'&&wn<='z') c[++h]=wn-'a',wn=getchar();
            Insert();
        }
        dfs(0);
        writeln(ans);
    }
    inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
    inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
    inline void writesp(ll x){write(x);putchar(' ');}
    inline void writeln(ll x){write(x);putchar('
    ');}
  • 相关阅读:
    软件工程学习总结
    南通大学教务管理系统微信平台 用户体验
    设计一款适合父母使用的手机
    我想搞懂的软工问题
    C++用法的学习心得
    email program (客户端)演变过程有感
    C++用法的学习心得
    软件工程学期总结
    微信南通大学教务学生管理系统_用户体验
    设计一款给父母使用的手机
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13362828.html
Copyright © 2011-2022 走看看