题 解 UVA11488 【하이퍼 접두사를 설정합니다】

주제 링크
첫째, 우리는 여러 데이터의 문자열뿐만 아니라 공통의 접두사를 찾는를 입력, 생각하기 쉽습니다 되는이 질문에 (트리는 \) \ 응용 프로그램

우리는 \ (트리는 \) 나무 위에 지어진 나무에 달려 \ (DP \)가 될 수 있습니다.

\ (DP (U, DIS) \) 로 표시 \은 (유 \) 서브 트리의 루트가, \ (U \) 깊이 \ (DIS \) 에 응답하면

쉽게 생각할 수있는 주체에 의해 정의 \ (DP (U, DIS) = 최대 \ {DIS TOT * [U], DP (V, DIS +. 1) \} \)

\ (TOT는 [U]는 \) 이다 (U \) \ 루트 서브 트리의 리프 노드의 수 (하기 즉, 루트 노드 (\ U \) 공통 접두어 기간, 공통 접두어를 갖는 문자열을 양 \ (TOT [U] \) )

그래서 우리는 차 코드를 기대할 수 있습니다 :

#include <bits/stdc++.h>
using namespace std;
struct Trie{
    static const int maxnode = 100100;
    static const int sigma_size = 2;
    int ch[maxnode][sigma_size];
    int val[maxnode];
    int sz;
    inline void init(){sz = 1;memset(ch[0],0,sizeof(ch[0]));memset(val,0,sizeof(val));}
    Trie(){sz = 1;memset(ch[0],0,sizeof(ch[0]));memset(val,0,sizeof(val));}
    inline int idx(char c){return c - '0';}
    inline void insert(const string &s){
        int u = 0,n = s.size();
        for(int i = 0;i < n;i++){
            int c = idx(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;        
            }
            u = ch[u][c];
        }
        val[u]++;
    }
    inline int tot(int u){
        int ret = val[u];
        for(int c = 0;c < sigma_size;c++)
            if(ch[u][c])ret += tot(ch[u][c]);
        return ret;
    }
    inline int dfs(int u,int dis){
        int ret = dis * tot(u);
        for(int c = 0;c < sigma_size;c++)
            if(ch[u][c])ret = max(ret,dfs(ch[u][c],dis + 1));
        return ret;
    }
}tt;
string ss;
int T,n;
inline void solve(){
    tt.init();      
    cin >> n;
    for(int i = 1;i <= n;i++){
        cin >> ss;
        tt.insert(ss);
    }
    printf("%d\n",tt.dfs(0,0));
}
int main(){
    ios::sync_with_stdio(false);
    cin >> T;
    while(T--)
        solve();
    return 0;
}

실행 코드 160 밀리 , 시간이 초과되지 않습니다,하지만 우리는 여전히 최적화를 고려한다.

모든 \ (DP \)를 고려하는됩니다 \ (TOT \) , 시간 현장에서 복잡성 폭발 (데이터 무해한 H2O하지만).

그때

우리는 구축 할 수 있습니다 \ (트리는 \) 때 나무를 \ (TOT \) 배열을 알아낼 수 있습니다.

일반적으로 내장 \ (트리는는 \) 나무 잎 노드는이 질문에 가치 권한을 부여하는 것입니다, 모든 무게는 우리가 점하는 동안 성과가된다 넣어 \을 (+ 1 \) , 이 권리는 각 노드의 값입니다 서브 트리의 루트 노드의 리프 노드의 수

코드 :

#include <bits/stdc++.h>//懒得打了,大家最好别用万能头文件
using namespace std;
struct Trie{
    static const int maxnode = 100100;//最大节点数
    static const int sigma_size = 2;//字符集大小
    int ch[maxnode][sigma_size];//儿子数组
    int val[maxnode];//节点附加权值,即转移方程的tot数组
    int sz;//当前节点总数
    inline void init(){sz = 1;memset(ch[0],0,sizeof(ch[0]));memset(val,0,sizeof(val));}//初始化函数
    Trie(){sz = 1;memset(ch[0],0,sizeof(ch[0]));memset(val,0,sizeof(val));}
    inline int idx(char c){return c - '0';}
    inline void insert(const string &s){//插入字符串,传引用避免拷贝开销
        int u = 0,n = s.size();
        for(int i = 0;i < n;i++){
            int c = idx(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;        
            }
            u = ch[u][c];
            val[u]++;//这里即上文所说的统计子树节点个数
        }
    }
    inline int dfs(int u,int dis){//最终答案
        int ret = val[u] * dis;
        for(int c = 0;c < sigma_size;c++)
            if(ch[u][c])
                ret = max(ret,dfs(ch[u][c],dis + 1));
        return ret;
    }
}tt;
string ss;
int T,n;
inline void solve(){//多组数据求解
    tt.init(); 
    cin >> n;
    for(int i = 1;i <= n;i++){
        cin >> ss;
        tt.insert(ss);
    }
    printf("%d\n",tt.dfs(0,0));
}
int main(){
    ios::sync_with_stdio(false);
    cin >> T;
    while(T--)
        solve();
    return 0;
}

추천

출처www.cnblogs.com/colazcy/p/11514703.html