2 条题解

  • 1
    @ 2025-4-25 11:50:03

    首先我们直接考虑每一个单词能否成为第一个

    首先第一种情况:如果一个单词 ii ,存在一个单词 jj 是单词 ii 的前缀,那么单词 ii 一定不可

    第二种情况,我们考虑建图:

    例如:abccba

    我们将每个单词的第 ii 位都与其他单词的第 ii 位连边,根据这个例子我们可以得到 c->aa->c 的图,表示 c 一定要大于 a 并且 a 也一定要大于 c

    但是这显然是不可能的,那也就是说如果建图出来环,一定不可,可以使用拓扑排序

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<queue>
    #define N 300005
    using namespace std;
    bool Test_MLE_start;
    int T=1,n,tot=1,ans=0;
    string s[N];
    bool vis[N],mp[27][27],ok[N];
    int t[N][27],wch[N],ind[27];
    inline int reads(){
    	char c=getchar();
    	int sum=0,f=1;
    	while(!isdigit(c)){
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(isdigit(c)){
    		sum=(sum<<3)+(sum<<1)+(c^'0');
    		c=getchar();
    	}
    	return sum*f;
    }
    inline void files(){
    	freopen("std.in","r",stdin);
    	freopen("std.out","w",stdout);
    }
    inline void clr(){
    //	Don't forget!
    	memset(mp,0,sizeof(mp));
    	memset(ind,0,sizeof(ind));
    }
    void inserts(int k){
    	int p=1,len=s[k].size();
    	for(register int i=0;i<len;i++){
    		int ch=s[k][i]-'a'+1;
    		if(!t[p][ch]) t[p][ch]=++tot;
    		p=t[p][ch];
    	}
    	vis[p]=1,wch[k]=p;
    }
    bool check1(int k){
    	clr();
    	int len=s[k].size(),p=1;
    	bool flg=1;
    	for(register int i=0;i<len;i++){
    		int ch=s[k][i]-'a'+1;
    		for(register int j=1;j<=26;j++){
    			if(j!=ch&&t[p][j]&&(!mp[ch][j])){
    				mp[ch][j]=1;
    				ind[j]++;
    			}
    		}
    		p=t[p][ch];
    		if(vis[p]&&wch[k]!=p) flg=0;
    	}
    	return flg;
    }
    bool check2(int k){
    	queue<int> q;
    	for(register int i=1;i<=26;i++) if(!ind[i]) q.push(i);
    	while(!q.empty()){
    //		cout<<q.size()<<"\n";
    		int x=q.front();
    		q.pop();
    		for(register int i=1;i<=26;i++){
    			if(mp[x][i]&&x!=i){
    				ind[i]--;
    				if(!ind[i]) q.push(i);
    			}
    		}
    	}
    	for(register int i=1;i<=26;i++){
    //		if(k==3) cout<<ind[i]<<" ";
    		if(ind[i]){
    //			if(k==3) cout<<(char(i+'a'-1))<<endl;
    			return 0;
    		}
    	}
    //	puts("");
    	return 1;
    }
    bool Test_MLE_end;
    signed main(){
    //	printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0);
    //	files();
    //	T=reads();
    	while(T--){
    		clr();
    		n=reads();
    		for(register int i=1;i<=n;i++){
    			cin>>s[i];
    			inserts(i);
    		}
    		for(register int i=1;i<=n;i++){
    			if(!check1(i)) continue;
    			if(!check2(i)) continue;
    			ans++,ok[i]=1;
    		}
    		printf("%d\n",ans);
    		for(register int i=1;i<=n;i++){
    			if(ok[i]) cout<<s[i]<<"\n";
    		}
    	}
    	return 0;
    }
    
    • -2
      @ 2025-4-25 9:53:14

      首先我们不难想到要建一个字典树

      然后对于每一个字符串,我们在查询的时候对除了他自己字符的其他能到的点连边,例:abc,aba,cba,我们要判abc,那么我们发现第一个字符有不一样的,于是a->c,第二个字符相同不管,第三个字符c->a,在所有字符都建完边后,我们判一判有没有环,如果有环的话,肯定不行

      然后就做完了

      • 1

      信息

      ID
      181
      时间
      1000ms
      内存
      256MiB
      难度
      7
      标签
      (无)
      递交数
      84
      已通过
      18
      上传者