[Bzoj4567] [loj # 2012] [SCOI2016] back word

Description

\ (Lweb \) facing a mountain of English words, into a deep meditation, "how can I quickly learn thoroughly, then play three killed it?." This time wise teacher from Phoenix floated away, he gave \ (Lweb \) a program book and a pickle vat, then the teacher told Phoenix \ (Lweb \) , I know the word you want to learn a total of there \ (n \) months, and now we plan to complete the table from top to bottom, for a sequence number \ (x \) word (number \ (1 ... x-1 \ ) have been filled in):

1. If there is a word is its suffix, and is not currently filled in the table, then he needs to eat \ (n \ times n \) stars Pickle to learn;
2. When it's all suffixes are filled table in the case, if the \ (1 ... x-1 \ ) word on the location of the suffix is not it, then he ate \ (x \) stars Pickle able to remember it;
3. when it All case suffixes are filled in the table, if \ (1 ... x-1 \ ) present position on its suffix word, all words in its extension, the maximum number of \ (Y \ ) , then he should eat \ (xy \) stars Pickle memorize it.
\ (Lweb \) is a spicy things will eat strange runaway children, so please help \ (Lweb \) , to find an optimal plan to fill in the word, making him remember that \ (n \) th in the case of the word, the least eat Pickle.

Input

Enter an integer representing \ (Lweb \) the number of words to be learned. Next \ (n-\) rows, each row has a word (consisting of lower case letters, and to ensure that any word twenty-two different from each other).

Output

\ (Lweb \) the minimum number of Pickle eat.

Sample Input


2

Sample Output

2

HINT

\ (. 1 \ n-Leq \ Leq. 5 ^ 10 \) , the sum of the lengths of all the characters \ (1 \ leq | len | \ leq 510000 \)


idea

All the strings in turn, built in \ (trie \) tree, forming a prefix tree, the original title of the suffix prefix that is where
an apparently greedy are all strings are filled and then fill it all the prefixes, \ (n \ times n \) the cost can not afford to.

Corresponds to the parent node in the tree is traversed, so that at all points in the former sub-access node, the access time is the total cost of all the points of difference between the sum of the parent node.
So another greedy, after each point of access by all its child nodes (size \) \ size, from small to large order of access.

It is easy to think of this greedy, but ye proved to be right? [I heard that this is a classic problem, but the Internet did not see much proof ah (escape]
can see \ (neither_nor \) proof https://blog.csdn.net/neither_nor/article/details/51362523


Code

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

using namespace std;

const int N = 110000;
typedef long long ll;

int n;
int fa[N],sz[N];

struct trie{
    trie *ch[26];
    int id;
}pool[N*5],*root;
int cnt;
void insert(char s[],int id){
    trie *p=root;
    int len=strlen(s);
    for(int i=len-1;i>=0;i--){
        if(!p->ch[s[i]-'a']) p->ch[s[i]-'a']=&pool[++cnt];
        p=p->ch[s[i]-'a'];
    }
    p->id=id;
}

struct node{
    node *nxt;
    int v;
}pool2[N],*h[N];
int cnt2;
void addedge(int u,int v){
    node *p=&pool2[++cnt2];
    p->v=v;p->nxt=h[u];h[u]=p;
}

void dfs(trie *p,int cur){
    int nc=p->id ? p->id : cur;
    for(int i=0;i<26;i++)
        if(p->ch[i])
            dfs(p->ch[i],nc);
    if(p->id){
        sz[p->id]++;
        fa[p->id]=cur;
        sz[cur]+=sz[p->id];
        addedge(cur,p->id);
    }
}

ll ans;
int b[N],tot;
void work(int u){
    for(node *p=h[u];p;p=p->nxt) work(p->v);
    tot=0;
    for(node *p=h[u];p;p=p->nxt) b[++tot]=sz[p->v];
    sort(b+1,b+1+tot);
    for(int i=1;i<=tot;i++)
        ans+=1ll*b[i]*(tot-i);
    ans+=tot;
}

int main()
{
    char s[N];
    scanf("%d",&n);
    root=&pool[++cnt];
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        insert(s,i);
    }
    dfs(root,0);
    
    ans=0; work(0);
    printf("%lld\n",ans);
    
    return 0;
}

Guess you like

Origin www.cnblogs.com/lindalee/p/11431890.html