https://vjudge.net/contest/311647#overview
给定n个串,求出每个串的“唯一最短前缀”
用bo[i]表示从字典树根节点0到节点i连成的字符串为前缀的单词个数,那么在查询一个单词的时候,在该路径的某个节点i出现了bo[i]=1的情况,就说明这个字符串是该单词的唯一前缀。
1 #include<iostream> 2 #include<sstream> 3 #include<fstream> 4 #include<algorithm> 5 #include<cstring> 6 #include<iomanip> 7 #include<cstdlib> 8 #include<cctype> 9 #include<vector> 10 #include<string> 11 #include<cmath> 12 #include<ctime> 13 #include<stack> 14 #include<queue> 15 #include<map> 16 #include<set> 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define random(a,b) (rand()%(b-a+1)+a) 19 #define ll long long 20 #define ull unsigned long long 21 #define e 2.71828182 22 #define Pi acos(-1.0) 23 #define ls(rt) (rt<<1) 24 #define rs(rt) (rt<<1|1) 25 #define lowbit(x) (x&(-x)) 26 using namespace std; 27 const int MAXN=2e4+5; 28 const int Z=26; 29 int ch[MAXN][Z]; 30 int bo[MAXN]; 31 char str[1001][21]; 32 int tot=1; 33 void insert(char *s) 34 { 35 int l=strlen(s),u=1; 36 for(int i=0;i<l;++i) 37 { 38 int c=s[i]-'a'; 39 if(!ch[u][c]) ch[u][c]=++tot; 40 u=ch[u][c]; 41 bo[u]++; 42 } 43 } 44 void query(char *s) 45 { 46 int l=strlen(s),u=1; 47 for(int i=0;i<l;++i) 48 { 49 int c=s[i]-'a'; 50 if(bo[u]==1) break; 51 putchar(s[i]); 52 u=ch[u][c]; 53 } 54 putchar(' '); 55 } 56 int main() 57 { 58 int cnt=0; 59 while(scanf("%s",str[++cnt])!=EOF) 60 insert(str[cnt]); 61 62 for(int i=1;i<=cnt;++i) 63 { 64 cout<<str[i]<<' '; 65 query(str[i]); 66 } 67 }
模糊匹配,一个'?'字符匹配任意一个字符,一个'*'字符匹配0个、1个或多个字符。
dfs和Trie的结合
两个指针在查询的字符串和Trie上走
1 #include<iostream> 2 #include<sstream> 3 #include<fstream> 4 #include<algorithm> 5 #include<cstring> 6 #include<iomanip> 7 #include<cstdlib> 8 #include<cctype> 9 #include<vector> 10 #include<string> 11 #include<cmath> 12 #include<ctime> 13 #include<stack> 14 #include<queue> 15 #include<map> 16 #include<set> 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define random(a,b) (rand()%(b-a+1)+a) 19 #define ll long long 20 #define ull unsigned long long 21 #define e 2.71828182 22 #define Pi acos(-1.0) 23 #define ls(rt) (rt<<1) 24 #define rs(rt) (rt<<1|1) 25 #define lowbit(x) (x&(-x)) 26 using namespace std; 27 const int MAXN=6e5+5; 28 //const int MAXN=1e5+5; 29 const int Z=28; 30 int ch[MAXN][Z]; 31 vector<int> bo[MAXN]; 32 vector<int> ans; 33 char str[30]; 34 bool isok[MAXN]; 35 bool visit[MAXN]; 36 int n,m,len; 37 int tot=1; 38 int read() 39 { 40 int s=1,x=0; 41 char ch=getchar(); 42 while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();} 43 while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();} 44 return x*s; 45 } 46 int f(char c) 47 { 48 if(c=='?') return 26; 49 if(c=='*') return 27; 50 return c-'a'; 51 } 52 void insert(char *s,int id) 53 { 54 int l=strlen(s),u=1; 55 for(int i=0;i<l;++i) 56 { 57 if(!ch[u][f(s[i])]) ch[u][f(s[i])]=++tot; 58 u=ch[u][f(s[i])]; 59 if(f(s[i])==27) isok[u]=true; 60 } 61 bo[u].push_back(id); 62 } 63 void find(int le,int u) 64 { 65 if(le==len) 66 { 67 int sz=bo[u].size(); 68 for(int i=0;i<sz;++i) 69 if(!visit[bo[u][i]]) 70 { 71 visit[bo[u][i]]=true; 72 ans.push_back(bo[u][i]); 73 } 74 if(ch[u][27]) find(le,ch[u][27]); 75 return; 76 } 77 int c=f(str[le]); 78 if(ch[u][c]) find(le+1,ch[u][c]);//精准匹配 79 if(ch[u][26]) find(le+1,ch[u][26]);//?字符匹配 80 if(ch[u][27])//*字符匹配 81 { 82 find(le+1,ch[u][27]);//匹配1个 83 find(le,ch[u][27]);//匹配0个 84 } 85 if(isok[u]) find(le+1,u);//*匹配多个 86 } 87 int main() 88 { 89 ios::sync_with_stdio(false); 90 cin.tie(0);cout.tie(0); 91 cin>>n>>m; 92 for(int i=1;i<=n;++i) 93 { 94 cin>>str; 95 insert(str,i-1); 96 } 97 for(int i=1;i<=m;++i) 98 { 99 cin>>str; 100 len=strlen(str); 101 ans.clear(); 102 mem(visit,0); 103 find(0,1); 104 int sz=ans.size(); 105 if(!sz) 106 { 107 cout<<"Not match"<<endl; 108 continue; 109 } 110 sort(ans.begin(),ans.end()); 111 for(int j=0;j<sz;++j) 112 { 113 if(j==sz-1) cout<<ans[j]<<endl; 114 else cout<<ans[j]<<' '; 115 } 116 } 117 return 0; 118 }
给定n个长度不超过10的数字串,问其中是否存在两个数字串S、T,使得S是T的前缀。 将所有的字符串构成一棵Trie,在构建过程中可以顺便判断答案。 若当前串插入后没有新建任何结点,则当前串肯定是之前插入的某个串的前缀; 若插入过程中,有某个经过的结点带有串结尾标记,则之前插入的某个串是当前串的前缀
1 #include<iostream> 2 #include<sstream> 3 #include<fstream> 4 #include<algorithm> 5 #include<cstring> 6 #include<iomanip> 7 #include<cstdlib> 8 #include<cctype> 9 #include<vector> 10 #include<string> 11 #include<cmath> 12 #include<ctime> 13 #include<stack> 14 #include<queue> 15 #include<map> 16 #include<set> 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define random(a,b) (rand()%(b-a+1)+a) 19 #define ll long long 20 #define ull unsigned long long 21 #define e 2.71828182 22 #define Pi acos(-1.0) 23 #define ls(rt) (rt<<1) 24 #define rs(rt) (rt<<1|1) 25 #define lowbit(x) (x&(-x)) 26 using namespace std; 27 const int MAXN=2e5+5; 28 const int Z=10; 29 int ch[MAXN][Z]; 30 int tot=1; 31 bool bo[MAXN]; 32 bool insert(char *s) 33 { 34 int l=strlen(s),u=1; 35 bool flag=false; 36 for(int i=0;i<l;++i) 37 { 38 int c=s[i]-'0'; 39 if(!ch[u][c]) ch[u][c]=++tot; 40 else if(i==l-1) flag=true; 41 u=ch[u][c]; 42 if(bo[u]) flag=true; 43 } 44 bo[u]=true; 45 return flag; 46 } 47 int read() 48 { 49 int s=1,x=0; 50 char ch=getchar(); 51 while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();} 52 while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();} 53 return x*s; 54 } 55 int main() 56 { 57 ios::sync_with_stdio(false); 58 cin.tie(0);cout.tie(0); 59 int test;cin>>test; 60 while(test--) 61 { 62 int n;cin>>n; 63 bool flag=false; 64 mem(ch,0);mem(bo,0); 65 tot=1; 66 char str[20]; 67 for(int i=1;i<=n;++i) 68 { 69 cin>>str; 70 if(insert(str)) flag=true; 71 } 72 if(flag) cout<<"NO"<<endl; 73 else cout<<"YES"<<endl; 74 } 75 }