1. 程式人生 > 其它 >CF838C-Future Failure【dp,子集卷積】

CF838C-Future Failure【dp,子集卷積】

和之前那個題目很像

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;
}