UVa11732 "strcmp()" Anyone?

原题

题目传送

题解

用Trie把所有单词合起来,插入一次就统计一次这个单词和已插入的单词比较的次数。也就是相同部分前缀长度*2+1.但是注意两个完全相同的单词比如说a a需要比4次,因为最后的结束符号也是一样的,还有就是左儿子右兄弟表示法,好好学习QAQ。

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000+10;
const int maxnode=4000000+10;
typedef long long ll;

struct Trienode{
    char ch;
    int cnt,val;
    Trienode *lc,*next;
    Trienode(){
        lc=next=NULL;
        val=cnt=ch=0;
    }
};
struct Trie{
    Trienode *root;
    Trie(){
        root=new Trienode();
    }
    inline void clear(){
        root=new Trienode();
    }
    inline ll insert(Trienode *p,char *s,int v){
        ll ret=0;
        int n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int x=0;
            Trienode *k=p->lc,*wh=NULL;
            for(;k;k=k->next)
            {
                if(k->ch==s[i])wh=k;
                else x+=k->cnt;
            }
            k=wh;
            if(!k)
            {
                k=new Trienode();
                k->next=p->lc;
                p->lc=k;
                k->ch=s[i];
            }
            if(x) ret=ret+(i*2+1)*x;

            if(i==n-1) 
            {
                ret=ret+((i+1)*2+1)*k->cnt;
                if(k->val) ret+=k->val;
            }
            else if(k->val) ret=ret+(2*(i+1)+1)*k->val;

            k->cnt++;
            p=k;
        }
        p->val+=v;
        return ret;
    }
}trie;

int kase=0,n;
char s[maxn];
void solve()
{
    trie.clear();
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s);
        ans+=trie.insert(trie.root,s,1);
    }
    printf("Case %d: %lld\n",++kase,ans);
    return ;
}

int main()
{
    while(scanf("%d",&n)==1&&n) solve();
    return 0;
}

你可能感兴趣的:(UVa11732 "strcmp()" Anyone?)