LDUOJ——前缀(字典树的链表优化)

简介: LDUOJ——前缀(字典树的链表优化)

原题链接

C. 前缀

Description

给你一个字符串集合,请从中找出一些字符串,使得找出来的这些字符串的最长公共前缀与字符串数的总个数的乘积最大化,并输出这个最大值。


Input

输入文件的第一行给出字符串个数n(1≤n≤1000000),下面n行描述这n个字符串,每个字符串长度不超过20000,输入文件大小在10MB之内


Output

输出一行一个数,表示最大化的结果


Samples

Input Copy

7

Jora de Sus

Orhei

Jora de Mijloc

Joreni

Jora de Jos

Japca

Orheiul Vechi

Output

24

Hint

数据范围 1≤n≤1000000

思路:

建立Trie树的同时记录深度和个数,相乘取max就好。

然后,卡内存,用二维数组存不行。


然而,对于本题来说这种方式并不太合适。因为本题中的字母有1000000个,在极端情况下,Trie树中结点的数量也可能到达这个数量级,字符集也没有规定,所以应该默认为256,如果按照这样一一种处理方式,所需要的内存可能达到9000MB,这显然大大超出了题中所给的限制,初始化一遍都会超时,如果把结点数开得少–些又有可能只得部分分。


然后就用链表优化吧,这里用的是链式前向星。

代码:

朴素版本:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
int son[maxn][110],cnt[maxn],idx=1;
int res=0;
void add(string s){
  int p=0,dep=0;
  for(int i=0;i<s.size();i++){
    int u;
    if(s[i]==' ') u=52;
    else if(s[i]>='a'&&s[i]<='z') u=s[i]-'a';
    else u=s[i]-'A'+26;
    if(son[p][u]) p=son[p][u];
    else p=son[p][u]=++idx;
    cnt[p]++;
    res=max(res,cnt[p]*(i+1));
  }
}
int main(){
  int n;
  cin>>n;
  getchar();
  for(int i=1;i<=n;i++){
    string s;
    getline(cin,s);
    ///cout<<s<<endl;
    add(s);
  }
  cout<<res<<endl; 
  return 0;
}

优化版本:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+7;
struct node{
  int ne,e,w;
}a[maxn];
int h[maxn],idx,cnt[maxn];
int tot=1;
void add(int u,int v,int w){
  a[idx]={h[u],v,w};h[u]=idx++;
}
int res=0;
void insert(string s){
  int p=1;
  for(int i=0;i<s.size();i++){
    int t=p;
    for(int j=h[p];~j;j=a[j].ne){
      if(a[j].w==s[i]) p=a[j].e;
    } 
    if(p==t) p=++tot,add(t,p,s[i]);
    cnt[p]++;
    res=max(res,cnt[p]*(i+1));
  }
}
int main(){
  int n;
  cin>>n;
  getchar();
  memset(h,-1,sizeof h);
  for(int i=1;i<=n;i++){
    string s;
    getline(cin,s);
    ///cout<<s<<endl;
    insert(s);
  }
  cout<<res<<endl; 
  return 0;
}

然后牛客的时限给了1s,没卡过去。LDUOJ的给了2s。



目录
相关文章
|
10天前
|
存储 NoSQL Redis
Redis第四弹,Redis实现list时候做出的优化ziplist(压缩链表,元素少的情况),可更好的节省空间list——(内部编码:quicklist)Object encoding
Redis第四弹,Redis实现list时候做出的优化ziplist(压缩链表,元素少的情况),可更好的节省空间list——(内部编码:quicklist)Object encoding
|
1月前
|
存储 算法 C语言
【C/C++ 链表结构】探索链表迭代器:C++实现的深入分析与优化策略
【C/C++ 链表结构】探索链表迭代器:C++实现的深入分析与优化策略
51 0
|
算法
算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表、删除排序链表中的重复元素
算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表、删除排序链表中的重复元素
85 0
|
C语言
[C语言]链表实现贪吃蛇及部分模块优化
在继上篇[C语言]贪吃蛇_结构数组实现大半年后,链表实现的版本也终于出炉了。两篇隔了这么久除了是懒癌晚期的原因外,对整个游戏流程的改进,模块的精简也花了一些时间(都是借口)。   优化模块的前沿链接:         ·游戏流程结构的改进         ·对输入的甄别与判断         ·单链表元素移动   一、游戏流程     贪吃蛇游戏的原理很简单,即在一张地图内,有一条蛇和随机出现的食物,玩家操控蛇的移动,当蛇吃到了食物后,蛇长度增加。
1004 0
|
1月前
【移除链表元素】LeetCode第203题讲解
【移除链表元素】LeetCode第203题讲解
|
6天前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
2天前
|
算法
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
|
6天前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
6天前
|
存储 SQL 算法
LeetCode 83题:删除排序链表中的重复元素【面试】
LeetCode 83题:删除排序链表中的重复元素【面试】