[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('
');}
原文地址:https://www.cnblogs.com/ylwtsq/p/13362828.html