UVa:11732 strcmp() Anyone?

来源:互联网 发布:中美合作 规范网络 编辑:程序博客网 时间:2024/05/01 07:29

折腾了两个多小时终于把这个题给过了。

一开始想到思路直接写了个多叉的tire,结果超时了。感觉是不能再小的算法了,后来发现只memset就要很长时间,于是改成每次开辟新节点的时候再memset,还加了读入输出外挂,结果还是超时。后来上网题解上说要用左儿子右兄弟表示法来做,然后写了一个,1.7sAC了。

多叉的写法,由于它直接利用下标表示对应的字符,所以对空间浪费比较严重,但是要找到某个结点的孩子结点是O(1)的。

而二叉的写法,是通过每次比较查找来找到对应字符的,所以没有浪费的空间,但是比较费时。

多叉和二叉的写法,就好像是邻接矩阵和邻接表似的。

这个题多叉写法会超时,大概是数组开的过大,每次memset超时了(想起之前写的几个tire的代码,也都很慢,可能是这个原因)。

用左儿子右兄弟的写法,原来每个case都把全部数组memset一遍,结果跑了1.8s。后来改掉了这块,改成每次建树的时候清空每个结点,变成了0.8s。

这个题的思路,每次建树的时候就考虑每个结点字符出现的次数,与当前结点之前出现次数的比较,这里比较两次,跟父亲结点的比较,这里要去掉父亲结点中当前结点的那块,只比较一次。

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <vector>#include <algorithm>#define ll long long#define INF 200000000#define MOD 20071027#define MAXN 4000*1005using namespace std;ll ans;struct Tire{    int child[MAXN],next[MAXN],val[MAXN];    char str[MAXN];    int sz;    void Init()    {        sz=1;        child[0]=0;        next[0]=0;        val[0]=0;    }    void Insert(char *word)    {        int u=0,v;        val[u]++;        for(int i=0; word[i]; ++i)        {            bool ok=false;            for(v=child[u]; v; v=next[v])            {                if(str[v]==word[i])                {                    ok=true;                    break;                }            }            if(!ok)            {                str[sz]=word[i];                val[sz]=0;                child[sz]=0;                v=sz++;                next[v]=child[u];                child[u]=v;            }            ans+=val[v]*2;            val[v]++;            ans+=val[u]-val[v];            u=v;        }    }};Tire tree;char word[1005];int main(){    int n,kase=0;    while(scanf("%d",&n)!=EOF&&n)    {        getchar();        ans=0;        tree.Init();        for(int i=0; i<n; ++i)        {            int j=0;            while(word[j]=getchar())            {                if(word[j]=='\n') break;                j++;            }            word[j]='#';            word[j+1]=0;            tree.Insert(word);        }        printf("Case %d: %lld\n",++kase,ans);    }    return 0;}


 

0 0
原创粉丝点击