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

简介: 给出 n 个字符串,对于每个 i ,找到最少需要多少个前缀,将第 1 -> i 个字符串的前缀包含在内,不包含第 i + 1 -> n 个字符串的前缀首先暴力的字典树解法(由于内存的加强,并不能通过该题)压缩Trie 是可以的

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


Description


In the upcoming n nn days, n nn 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\n", 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\n", 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\n",sum[i]);
}






目录
相关文章
|
6月前
|
存储 算法 vr&ar
☆打卡算法☆LeetCode 208. 实现 Trie (前缀树) 算法解析
☆打卡算法☆LeetCode 208. 实现 Trie (前缀树) 算法解析
|
机器学习/深度学习 Java
【Java每日一题,dfs】[USACO1.5]八皇后 Checker Challenge
【Java每日一题,dfs】[USACO1.5]八皇后 Checker Challenge
|
C++
【PAT甲级 - C++题解】1043 Is It a Binary Search Tree
【PAT甲级 - C++题解】1043 Is It a Binary Search Tree
90 0
【PAT甲级 - C++题解】1043 Is It a Binary Search Tree
|
测试技术
牛客hot100--BM17---二分查找I(简单难度)
牛客hot100--BM17---二分查找I(简单难度)
120 0
牛客hot100--BM17---二分查找I(简单难度)
|
人工智能
Codeforces1501——C. Going Home(鸽巢原理)
Codeforces1501——C. Going Home(鸽巢原理)
72 0
[HDU7073] Integers Have Friends 2.0 -随机大法好
题意: 找到最大的一个集合,使得集合内所有元素 % m(>=2) 问最大的集合大小
94 0
[HDU7073] Integers Have Friends 2.0 -随机大法好