uva 11732 – strcmp() Anyone? 不错的Trie题

uva 11732 – strcmp() Anyone? 不错的Trie题

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

题解:http://blog.csdn.net/u013480600/article/details/23122503

我的代码一直TLE,,,看了人家的之后,认为1、链式前向星比較好,2、*depth而不是每过一个节点就计算,这一点非常好

我是基本copy别人的代码,自己加了凝视,留个记号,随后重写,

这道题相同作为链式前向星的Trie的模板

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

using namespace std;
#define ll long long
const int MAXN=4002*1002+100;

struct Trie
{
    int head[MAXN];//其值为在边集的下标
    int next[MAXN];//next[j]第j条边的下一条边在边集的下标
    int tot[MAXN];
    char str[MAXN];//相当于边集了 边存储字符
    int sz;//head下标的上界,也相当于节点
    ll ans;
    void clear()
    {
        ans=0;
        sz=1;
        head[0]=next[0]=tot[0]=0;

    }
    void insert(char *s)
    {
        int n=strlen(s),u=0;
        tot[u]++;
        for(int i=0;i<=n;i++)//空字符也插入
        {
            bool found=false;
            for(int j=head[u];j;j=next[j])
                if(str[j] == s[i])
                {
                    u=j;
                    found=true;
                    break;
                }
            if(!found)//节点不存在
                {
                    next[sz]=head[u];
                    head[u]=sz;

                    head[sz]=0;//
                    tot[sz]=0;//新的节点还没有连边
                    str[sz]=s[i];//初始化边信息,边存储字符
                    u=sz++;//u存储新的子结点
                }
                tot[u]++;
        }
    }
    void dfs(int dep, int u)
    {
        if(!head[u])//到了叶子节点
        {
            ans+=tot[u]*(tot[u]-1)*dep;
        }
        else
        {
            int sum=0;
            for(int v=head[u];v;v=next[v])  //**
                sum+=tot[v]*(tot[u]-tot[v]);//**
            ans+= sum/2*(dep*2+1);//这里我自己做的时候没有想到,,,,事实上分叉后跟分叉前都能够用上面标注**的方法计算
            for(int v=head[u];v;v=next[v])
                dfs(dep+1,v);
        }
    }
    ll cal()
    {
        ans=0;
        dfs(0,0);
        return ans;
    }
};
Trie trie;
char word[1000+100];
int main()
{

    int icase=0,n;
    while(scanf("%d",&n) && n)
    {
        trie.clear();
        for(int i=0;i<n;i++)
        {
            scanf("%s",word);
            trie.insert(word);
        }
        printf("Case %d: %lld\n",++icase,trie.cal());
    }
    return 0;
}

我的tle的代码  随后改动

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

using namespace std;

#define ll long long

const int N = 4011*1000+10;
const int tk = 75;
const int tb = '0'; // tk叉; 起始字母为tb;
int top, tree[N][tk + 2];  // N: 最大结点个数 top: 第一层有多少节点
char str[1010];
void init(){
    top = 1;
    memset(tree[0], 0, sizeof(tree[0]));
}

void Insert(char*s, int Rank = 1){
    int rt, nxt;
    for(rt = 0; *s; rt = nxt, ++s) {
        nxt = tree[rt][*s - tb];

        if(0 == nxt) {//没被使用时插入
            tree[rt][*s - tb] = nxt = top;
            memset(tree[top], 0, sizeof(tree[top]));
            top++;
        }
        tree[nxt][tk]++;//其值表示有多少单词经过
    }
    tree[rt][tk+1] = Rank;//1表示存在0表示不存在,也能够赋予其其它含义
}

ll solve(int rt,int last)
{
    if(tree[rt][tk] <= 1)return 0;
    //到结尾仅仅须要比較一次,假设仅仅有一个,也仅仅须要比較一次
    ll ans=0;
    for(int i=0;i<tk;i++)
        if(tree[rt][i])
        {
            ans=ans+tree[tree[rt][i]][tk]*(last-tree[tree[rt][i]][tk]);//计算子树森林
        }

    ans/=2;
    for(int i=0;i<tk;i++)
    {
        if(tree[rt][i])
        {
            ans+=solve(tree[rt][i],tree[tree[rt][i]][tk]);
        }

    }
    //return ans+2*C[tree[rt][tk]][2];
    return ans+tree[rt][tk]*(tree[rt][tk]-1);
}
int main()
{
    freopen("uva11732.txt","r",stdin);
    int icase=0,n,len;
    //calC();
    while(scanf("%d",&n)==1 && n)
    {
        init();
        tree[0][tk]=n;
        for(int i=0;i<n;i++)
        {
            scanf("%s",str);
            Insert(str);
        }

        printf("Case %d: %lld\n",++icase,solve(0,n)-n*(n-1));
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118262.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java 日志处理[通俗易懂]

    java各日志组件介绍common-logging(同时也称JCL)  common-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging,common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。当然,common-loggi…

    2022年4月16日
    44
  • vmware linux安装_vm如何安装系统

    vmware linux安装_vm如何安装系统火眼发布Windows渗透工具包(CommandoVM)包含140个渗透工具工具下载地址:github.com/fireeye/commando-vmKaliLinux已成为攻击型安全专家的标配工具,但对需要原生Windows功能的渗透测试员来说,维护良好的类似工具集却是不存在的。安全服务公司火眼就是要改变这一现状。3月28日,该公司发布了一个包含超过140个开源Windows工具的…

    2022年10月1日
    0
  • 正弦,余弦,正切,余切,正割,余割_三角函数的正弦余弦是什么意思

    正弦,余弦,正切,余切,正割,余割_三角函数的正弦余弦是什么意思三角函数三角函数包括正弦、余弦、正切、余切、正割、余割函数0基础知识正弦(Sine):sinA=CB/CA余弦(Cosine):cosA=AB/CA正切(Tangent):tanA=CB/BA余切(Cotangent):cotA=1/(tanA)BA/CB正割(Secant):secA=1/(cosA)=CA/AB余割(Cosecant):cosecA=1/(sinA)=CA/CB1y=sinx2y=cosx

    2022年10月24日
    0
  • CompoundButton(checkbox,switch,ToggleButton)和RadioGroup OnCheckedChangeListener() 引用冲突问题

    CompoundButton(checkbox,switch,ToggleButton)和RadioGroup OnCheckedChangeListener() 引用冲突问题在一个类中同时有CompoundButton和RadioGroup  vSwitch.setOnCheckedChangeListener(newOnCheckedChangeListener(){ @Override publicvoidonCheckedChanged(CompoundButtonbuttonView,booleanisChecke

    2022年5月2日
    31
  • 基于51单片机步进电机控制[通俗易懂]

    基于51单片机步进电机控制[通俗易懂]实现功能:1、用矩阵键盘设定电机目标转速及旋转方向,范围100~300转/分;2、测量、显示电机实际转速和方向(正转显示“P”,反转显示“N”);从实现功能上分析,软件可以分解3个功能模块:1,步进电机控制模块2,矩阵键盘输入模块3,显示输出模块步进电机工作原理步进电机通过输入脉冲信号进行控制,即电机的总转动角度由输入脉冲总数决定,而电机的转速…

    2022年5月31日
    31
  • 物联网的体系架构概述[通俗易懂]

    物联网的体系架构概述[通俗易懂]物联网物联网有别于互联网,互联网的主要目的是构建一个全球性的信息通信网络,而物联网则侧重信息服务,即利用互联网、无线通信等进行业务信息的传送,服务对象由人转变为包括人在内的所有物品。物联网作为互联网的延伸,通过将智能物件整合到数字世界,面向用户提供个性化和私有化服务。物联网的体系架构应包括如下内涵:网络体系架构、技术与标准体系、资源与标识体系、产业与应用体系、服务与安全体系。(图)USNUSN体系架构是由韩国电子与通信技术研究所在2007年瑞士日内网召开的ITU下一代网络全球标准化会议(NUN-U

    2022年9月15日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号