Codeforces 861D - Polycarp's phone book 字典树/hash
输入7e4个字符串,要求每个串提取一个子串来唯一表示
4s题可以hash暴力水过,大体思路就是把所有子串map自己的母串,过程中如果这个子串已有hash值就标-1
然后枚举map元素,维护最小化一下就行了
唯一要注意的就是十进制哈希方式区分不了00和0
另一种做法是字典树存下所有子串,
枚举母串,枚举子串,字典树删掉子串,树中查子串个数是不是0,是的话维护一下最小就行了
复杂度胜在字典树上短的先拿到?
主要还是因为字典树没个熟悉的板子所以想练练。。
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=5e6+9; const int sigma=10; int mx; char a[70010][10],tmp[10],ans[10]; struct NODE{ int nxt[10]; int val; void init(){ val=0;memset(nxt,0,sizeof nxt); } }trie[maxn]; int node_cnt=0; void insert(char *s){ int len=strlen(s); int now=0; for(int i=0;i<len;i++){ int id=s[i]-'0'; int to=trie[now].nxt[id]; if(to==0){ to=++node_cnt; trie[to].init(); trie[now].nxt[id]=to; } trie[to].val+=1; now=to; } //trie[now].v=0; } void del(char *s){ int len=strlen(s); int now=0; for(int i=0;i<len;i++){ int id=s[i]-'0'; int to=trie[now].nxt[id]; //trie[to].init(); trie[to].val--; now=to; } } int query(char *s){ int len=strlen(s); int now=0; for(int i=0;i<len;i++){ tmp[i]=s[i]; int id=s[i]-'0'; int to=trie[now].nxt[id]; //if(to==-1)return -1; if(trie[to].val==0){ if(i+1<mx){ mx=i+1; tmp[i+1]='\0'; strcpy(ans,tmp);break; } } now=to; } //return trie[now].val; } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",a[i]); for(int j=0;j<9;j++) insert(a[i]+j); } for(int i=1;i<=n;i++){ mx=10; for(int j=0;j<9;j++) del(a[i]+j); for(int j=0;j<9;j++) query(a[i]+j); for(int j=0;j<9;j++) insert(a[i]+j); printf("%s\n",ans); } }