• [Nowcoder] Browser Games-2021牛客多校10-A | Hash /压缩Trie


    本题哈希做法参考博客:链接

    Description

    In the upcoming n n n days, n n n browser games will be released on a new website. According to the plan, the administrator will release a new game per day. Users have to open the corresponding URL (Uniform Resource Locator) and get feedback from the server to download a game.

    However, the setup of the server uses unreadable legacy codes. Once a user somehow finds the URL of an unreleased game, the data of the game would leak out. To temporarily fix the problem, the administrator decided to add a series of confirmation prefixes, which are non-empty strings, at the server-side. The server will respond with the correct game data when the requested URL does correspond to a game (no matter released or unreleased) and at least one confirmation prefix is a prefix of the URL; otherwise, the server will declare that the game is not found.

    To make the work easier, the administrator asks you to find the minimum number of confirmation prefixes the server required to avoid data leaks every time after a new game release.

    Input

    The first line contains an integer n (1≤n≤5×104), indicating the number of browser games to be released.

    In the next n lines, the i-th line contains a non-empty string, consisting of only lowercase letters (‘a’ to ‘z’), dots (‘.’) and forward slashes (‘/’), indicating the URL of the browser game released on the i-th day.

    It is guaranteed that the length of each given URL is at most 50, and no given URL is the prefix of any other given URL.

    Output

    Output n lines, the i-th of which contains an integer indicating the minimum number of required confirmation prefixes after the i-th new game released.

    Input Copy

    3
    ufoipv.ofu
    hsbocmvfgboubtz.kq
    hfotijo.njipzp.dpn/kb
    

    Output

    1
    2
    2
    

    给出 n 个字符串,对于每个 i ,找到最少需要多少个前缀,将第 1 -> i 个字符串的前缀包含在内,不包含第 i + 1 -> n 个字符串的前缀

    首先暴力的字典树解法(由于内存的加强,并不能通过该题)
    压缩Trie 是可以的

    const int maxn = 2600007;
    const int N = 5e4 + 7;
    int n, rt, idx, ans;
    int tree[maxn][30];
    char s[maxn][60];
    int last[maxn];
    ll pre[maxn];
    int getId(char c) {
        if(c == '.')
            return 1;
        else if(c == '/')
            return 2;
        else
            return (int)(c - 'a' + 3);
    }
    void Insert(char ss[], int id) {
        rt = 0;
        int len = strlen(ss);
        for(int i=0;i<len;i++){
            int x = getId(ss[i]);
            if(!tree[rt][x]) tree[rt][x] = ++ idx;
            last[tree[rt][x]] = id;
            rt = tree[rt][x];
        }
    }
    void Update(char ss[], int id) {
        int x = 0, pre_pos = 0, rt = 0;
        int len = strlen(ss);
        for(int i = 0; i < len; i++) {
            x = getId(ss[i]);
            int pos = last[tree[rt][x]];
            if(pos == id) {
                if(i == 0) {
                    pre[id] ++;
                    return;
                } else {
                    pre[id] ++;
                    pre[pre_pos] --;
                    return;
                }
            }
            rt = tree[rt][x];
            pre_pos = pos;
        }
    }
    int main() {
        n = read, idx = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%s", s[i]);
            Insert(s[i], i);
        }
        for(int i = 1; i <= n; i++)
            Update(s[i], i);
        ans = 0;
        for(int i = 1; i <= n; i++) {
            ans += pre[i];
            printf("%d
    ", ans);
        }
        return 0;
    }
    /**
    
    
    **/
    

    哈希做法:

    #define ull unsigned long long
    struct Hash {
        static const ull md1 = 1e9 + 7, md2 = 1e9 + 9;
        ull has1, has2;
        /// Hash() {}
        Hash(ull h1=0, ull h2=0): has1(h1), has2(h2) {}
        Hash operator+(const Hash& p) const {
            return Hash((has1 + p.has1) % md1, (has2 + p.has2) % md2);
        }
        Hash operator*(const Hash& p) const {
            return Hash((has1 * p.has1) % md1, (has2 * p.has2) % md2);
        }
        ull getVal() {
            return has1 * md2  + has2;
        }
    } Has[maxn], base(233, 2333);
    unordered_map<ll, vector<int> > mp;
    char s[maxn][117];
    int pos[maxn], ans[maxn];
    int main() {
        int n = read;
        for(int i = 1; i <= n; i++) {
            scanf("%s", s[i]);
            Has[i] = Hash(s[i][0], s[i][0]);
            mp[Has[i].getVal()].push_back(i);
            pos[i] = 0;
        }
        for(int i = n; i >= 1; i--) {
            ans[i] = mp.size();
            int len = strlen(s[i]);
            Hash temp;
            for(int j = 0; j < len; j++) {
                temp = temp * base + Hash(s[i][j], s[i][j]);
                auto at = mp.find(temp.getVal());
                if(at != mp.end()) {
                    for(int k : at->second) {
                        if(k != i) {
                            pos[k] ++;
                            Has[k] = Has[k] * base + Hash(s[k][pos[k]], s[k][pos[k]]);
                            mp[Has[k].getVal()].push_back(k);
                        }
                    }
                    mp.erase(at);
                }
            }
        }
        for(int i = 1; i <= n; i++)
            printf("%d
    ", ans[i]);
        return 0;
    }
    /**
    
    
    **/
    

    标称做法:

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    #define maxm 105
    int sum[maxn];
    char s[maxn][maxm];
    int n;
    int date[maxn];
    bool cmp(int a,int b) {
    	return strcmp(s[a]+1,s[b]+1)<0;
    }
    void solve(int l,int r,int end,int k) {
    	int nzk=0;
    	if(l==r)return;
    	for(int i=l,last=l; i<=r; i++) {
    		nzk=max(nzk,date[i]);
    		if(i==r||s[date[i]][k]!=s[date[i+1]][k]) {
    			sum[nzk]++;
    			sum[end]--;
    			solve(last,i,nzk,k+1);
    			last=i+1,nzk=0;
    		}
    	}
    }
    int main() {
    	scanf("%d",&n);
    	for(int i=1; i<=n; i++)
    		scanf("%s",s[i]+1),date[i]=i;
    	sort(date+1,date+1+n,cmp);
    	solve(1,n+1,n+1,1);
    	for(int i=2; i<=n; i++)
    		sum[i]+=sum[i-1];
    	for(int i=1; i<=n; i++)
    		printf("%d
    ",sum[i]);
    }
    
  • 相关阅读:
    C#基础:单例模式与多线程
    C#基础:线程同步
    C#基础:C#中的数据结构
    C#基础:GC中什么是代,一共分几代
    C#基础:Dispose方法和Finalize方法在何时被调用
    C#基础:.NET中GC的运行机制
    C#基础:简述.NET中堆栈和堆的特点和差异
    PLSQL_基础系列05_视图控制WITH CHECK OPTION(案例)
    PLSQL_基础系列04_时间间隔INTERVAL(案例)
    PLSQL_基础系列03_合并操作UNION / UNION ALL / MINUS / INTERSET(案例)
  • 原文地址:https://www.cnblogs.com/PushyTao/p/15459806.html
Copyright © 2020-2023  润新知