[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]);
}
原文地址:https://www.cnblogs.com/PushyTao/p/15459806.html