牛客練習賽11 B.假的字串 (trie+拓撲排序
阿新 • • 發佈:2018-12-16
先全部存入字典樹。
然後一個個判。可以得到mp[26][26]矩陣代表mp[x][y]。x字母要大於y字母。
然後檢查這個矩陣有沒有矛盾就行了。//拓撲排序找環
注意包含關係則大的那個不能輸出。
#include <iostream> #include <stdio.h> #include <cmath> #include <string.h> #include <map> #include <algorithm> using namespace std; typedef long long LL; const LL maxn = 30000+33; struct node { string s; int pos; }a[maxn],ans[maxn]; int tree[300111][30]; int val[300111]; int sz=0; int b[30]; void add(string s) { int len=s.length(); int to=0; for(int i=0;i<len;i++){ int x=s[i]-'a'; if(tree[to][x]==0){ tree[to][x]=++sz; } to=tree[to][x]; } val[to]=1; } bool query(string s) { int mp[30][30]; memset(mp,0,sizeof mp); int len=s.length(); int to=0; for(int i=0;i<len;i++){ int x=s[i]-'a'; int num=0; for(int j=0;j<='z'-'a';j++){ if(j==x) continue; if(tree[to][j]!=0){ mp[x][j]=1; } } if(val[to]==1) return false; to=tree[to][x]; } int du[30]; memset(du,0,sizeof du); for(int i=0;i<26;i++){ for(int j=0;j<26;j++){ if(mp[i][j]==1){ du[j]++; } } } for(int i=1;i<=26;i++){ int flag=1; for(int j=0;j<26;j++){ if(du[j]==0){ for(int k=0;k<26;k++){ if(mp[j][k]){ du[k]--; } } flag=0; du[j]=-1; break; } } if(flag) return false; } return true; } bool cmd2(node a,node b) { return a.pos<b.pos; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++){ cin>>a[i].s; a[i].pos=i; add(a[i].s); } int cnt=0; for(int i=1;i<=n;i++){ if(query(a[i].s)){ ans[++cnt].s=a[i].s; ans[cnt].pos=a[i].pos; } } printf("%d\n",cnt); sort(ans+1,ans+1+cnt,cmd2); for(int i=1;i<=cnt;i++){ cout<<ans[i].s<<endl; } }