• 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。

  • 相关阅读:
    android 进程/线程管理(一)----消息机制的框架
    android的屏幕保持常亮
    android network develop(3)----Xml Parser
    android network develop(2)----network status check
    android network develop(1)----doing network background
    android 开发小记
    转 Android中shape中的属性大全
    转 Android学习 之 ColorStateList按钮文字变色
    《大话设计模式》c++实现 建造者模式
    《大话设计模式》c++实现 外观模式
  • 原文地址:https://www.cnblogs.com/OvOq/p/14853053.html
Copyright © 2020-2023  润新知