CF838C-Future Failure【dp,子集卷積】
阿新 • • 發佈:2022-03-31
和之前那個題目很像
https://www.cnblogs.com/wzxbeliever/p/16087337.html
我想的是
先建立字典樹 依次判斷每個字串 對於同一深度 只要滿足該字元比其他字元前面就好
到這裡都是沒問題的 我開始想的是每層依次判斷26個字母滿不滿足 於是開心的提交了 發現tle
於是發現了問題 每層會浪費很多比較 所以想辦法改進 和上面那個題目一樣 用拓撲排序
當出現環的時候 那一定是不能滿足的 最後還要特判一下是否該字串字首為另一個字串 如果是的話 那肯定是沒法滿足的
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int maxn=3e4+5; int n,cnt,ans; int inn[30],sum[maxn*26],pd[maxn],tr[maxn*26][26]; string s[maxn]; vector<int>Q[30]; void insert(string); void tp(); bool ck(string); int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>s[i],insert(s[i]); for(int i=1;i<=n;i++) if(ck(s[i]))ans++,pd[i]=1; cout<<ans<<endl; for(int i=1;i<=n;i++) if(pd[i])cout<<s[i]<<endl; return 0; } void insert(string ss){ int rt=0; for(int i=0;i<ss.size();i++){ int id=ss[i]-'a'; if(!tr[rt][id])tr[rt][id]=++cnt; rt=tr[rt][id]; } sum[rt]++; } queue<int>q; void tp(){ while(!q.empty())q.pop(); for(int i=0;i<26;i++) if(!inn[i])q.push(i); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<Q[u].size();i++){ int to=Q[u][i]; inn[to]--; if(!inn[to]) q.push(to); } } } bool ck(string ss){ for(int i=0;i<26;i++)Q[i].clear(),inn[i]=0; int rt=0; for(int i=0;i<ss.size();i++){ int id=ss[i]-'a'; int now=tr[rt][id]; if(sum[rt])return false; for(int j=0;j<26;j++) if(tr[rt][j]&&j!=id) Q[id].push_back(j),inn[j]++; rt=now; } tp(); for(int i=0;i<26;i++) if(inn[i])return false; return true; }