MnZn 求助贪心 hack
查看原帖
MnZn 求助贪心 hack
420129
Nt_Tsumiki楼主2024/7/9 10:53

rt

50pts,用的 AC 自动机,大概是给 fail 树儿子排序时出了点正确性问题。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>

#define N 510001
#define LL long long

using namespace std;
int n; char s[N];

vector<int> e[N];

int tot,ch[N][26],fail[N],vis[N],siz[N],val[N];

void ins(char *s,int len) {
    int p=0;
    for (int i=0;i<len;i++) {
        if (!ch[p][s[i]-'a']) ch[p][s[i]-'a']=++tot;
        p=ch[p][s[i]-'a'];
    }
    vis[p]=1;
}

void getfail() {
    queue<int> q;
    for (int i=0;i<26;i++) 
        if (ch[0][i]) q.push(ch[0][i]);
    while (!q.empty()) {
        int x=q.front(); q.pop();
        for (int i=0;i<26;i++)
            if (ch[x][i]) fail[ch[x][i]]=ch[fail[x]][i],q.push(ch[x][i]);
            else ch[x][i]=ch[fail[x]][i];
    }
    for (int i=1;i<=tot;i++) e[fail[i]].push_back(i);
}

int num; LL ans;

void dfs0(int u) {
    val[u]=siz[u]=vis[u];
    for (int v:e[u]) {
        dfs0(v);
        siz[u]+=siz[v];
        if (!vis[u]) {
            if (vis[v]) val[u]++;
            else val[u]+=val[v];
        }
    }
}

void dfs(int u,int las) {
    if (vis[u]) ++num,ans+=num-las,las=num;
    for (int v:e[u]) dfs(v,las);
}

int main() {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {
        cin>>s; int len=strlen(s);
        ins(s,len);
    }
    getfail(); dfs0(0);
    for (int i=0;i<=tot;i++) sort(e[i].begin(),e[i].end(),[](int tmp1,int tmp2) { return siz[tmp1]^siz[tmp2]?siz[tmp1]<siz[tmp2]:val[tmp1]>val[tmp2]; });
    dfs(0,0);
    printf("%lld\n",ans);
    return 0;
}
2024/7/9 10:53
加载中...