UVa:11488 Hyper Prefix Sets

Tire。

思路很蠢,每个串的最后一个结点记录该串出现次数。然后在树上dfs求相同结点数*串个数的最大值。

第一次用scanf超时,后来改成gets,优化了一下读入,1.8s水过。。。

后来发现了,下面两份代码都是,时间主要花费在memset上面了,由于数组太大,memset花费时间太长,每次开始的时候没必要memset,而是建树的时候清空就可以了。

改了之后速度快了很多。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define INF 200000000
#define MOD 20071027
#define MAXN 5005
using namespace std;
int sz;
int ch[10000005][3],val[10000005];
void Init()
{
    sz=1;
    memset(ch[0],0,sizeof(ch[0]));
    val[0]=1;
}
int idx(char c)
{
    return c-'0';
}
void Insert(char *word)
{
    int u=0;
    for(int i=0; word[i]; ++i)
    {
        int x=idx(word[i]);
        if(ch[u][x]==0)
        {
            memset(ch[sz],0,sizeof(ch[sz]));
            val[sz]=0;
            ch[u][x]=sz++;
        }
        u=ch[u][x];
    }
    val[u]++;
}
int ans=0;
int solve(int u,int cur)
{
    if(!u) return 0;
    int cnt=solve(ch[u][0],cur+1)+solve(ch[u][1],cur+1)+val[u];
    ans=max(cur*cnt,ans);
    return cnt;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        int n;
        scanf("%d",&n);
        char word[205];
        getchar();
        for(int i=0; i<n; ++i)
        {
            gets(word);
            Insert(word);
        }
        ans=0;
        solve(ch[0][0],1);
        solve(ch[0][1],1);
        printf("%d\n",ans);
    }
    return 0;
}
 

网上看到的思路,对于每个结点保存它的长度和出现次数。这样只需要遍历所有结点,取长度*次数的最大值即可。

相比我的思路,这个思路在建树的时候就保留了有用的信息。而我的还需要遍历到树的叶子结点才行。

总感觉我的思路也是O(n)的。。

但是这个代码速度也很慢。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define INF 200000000
#define MOD 20071027
#define MAXN 5005
using namespace std;
int sz;
int ch[10000005][3],val[10000005],len[10000005];
void Init()
{
    sz=1;

    memset(ch[0],0,sizeof(ch[0]));
    val[0]=1;
}
int idx(char c)
{
    return c-'0';
}
void Insert(char *word)
{
    int u=0;
    for(int i=0; word[i]; ++i)
    {
        int x=idx(word[i]);
        if(ch[u][x]==0)
        {
            memset(ch[sz],0,sizeof(ch[sz]));
            val[sz]=0;
            ch[u][x]=sz++;
        }
        u=ch[u][x];
        len[u]=i+1;
        val[u]++;
    }
}
int ans=0;
int buf[10];
inline void writeint(int i)
{
    int p=0;
    if(i==0) p++;
    else while(i)
        {
            buf[p++]=i%10;
            i/=10;
        }
    for(int j=p-1; j>=0; --j) putchar(buf[j]+'0');
    putchar('\n');
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        int n;
        scanf("%d",&n);
        char word[205];
        getchar();
        for(int i=0; i<n; ++i)
        {
            gets(word);
            //scanf("%s",word);
            Insert(word);
        }
        ans=0;
        for(int i=1; i<sz; ++i)
            ans=max(ans,len[i]*val[i]);
        printf("%d\n",ans);
        //writeint(ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值