zoukankan      html  css  js  c++  java
  • 【[USACO12DEC]第一!First!】

    一个串不能成为第一的情况有两种

    1. 另外一个单词是它的前缀

    2. 在分配字母表大小关系的时候出现了矛盾的情况

    第一种很好判断,一旦我们在一个单词没有匹配完之前遇到一个结束标志,那么就说明另外一个单词是它的前缀

    至于第二种,看到大小关系和是否矛盾我们很容易就联想到了拓扑排序

    于是我们匹配的时候,发现某一层除了当前正在匹配的串以外还有其他字母,那么这些字母在我们构建的字母表中必须大于当前的这个字母,于是我们连一条有向边表示一下大小关系就好了

    最后跑一遍拓扑判断一下是否有环就好了

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<string>
    #define re register
    #define maxn 300005
    using namespace std;
    struct node
    {
    	int v,nxt;
    }e[1005];
    int son[maxn][26],flag[maxn];
    std::string S[30005];
    int len[30005];
    int n,num,cnt,tot;
    int head[26];
    int ans[maxn];
    inline void add_edge(int x,int y)
    {
    	e[++num].v=y;
    	e[num].nxt=head[x];
    	head[x]=num;
    }
    inline void ins(int x)
    {
    	int now=0;
    	for(re int i=0;i<len[x];i++)
    	{
    		if(!son[now][S[x][i]-'a']) son[now][S[x][i]-'a']=++cnt;
    		now=son[now][S[x][i]-'a'];
    	}
    	flag[now]=1;
    }
    inline int check(int x)
    {
    	int now=0;
    	memset(e,0,sizeof(e));
    	int c[26];
    	memset(c,0,sizeof(c));
    	memset(head,0,sizeof(head));
    	num=0;
    	for(re int i=0;i<len[x];i++)
    	{
    		if(flag[now]) return 0;
    		for(re int j=0;j<26;j++)
    		if(son[now][j]&&S[x][i]-'a'!=j)
    			add_edge(S[x][i]-'a',j),c[j]++;
    		now=son[now][S[x][i]-'a'];
    	}
    	int cur=0;
    	int q[27];
    	memset(q,0,sizeof(q));
    	for(re int i=0;i<26;i++)
    	if(!c[i]) q[++cur]=i;
    	for(re int i=1;i<=cur;i++)
    	{
    		for(re int j=head[q[i]];j;j=e[j].nxt)
    		{
    			c[e[j].v]--;
    			if(!c[e[j].v]) q[++cur]=e[j].v;
    		}
    	}
    	return cur==26;
    }
    int main()
    {
    	ios::sync_with_stdio(false);
        cin>>n;
    	for(re int i=1;i<=n;i++)
    	{
    		cin>>S[i];
    		len[i]=S[i].size();
    		ins(i);
    	}
    	tot=0;
    	for(re int i=1;i<=n;i++)
    		if(check(i)) ans[++tot]=i;
    	cout<<tot<<endl;
    	for(re int i=1;i<=tot;i++)
    	cout<<S[ans[i]]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    Kaldi的data目录解析
    Kaldi的nnet3
    Kaldi中的Chain模型
    Karel版本的nnet1
    Dan版本的nnet2
    MFCC/Filter Bank的提取流程
    【算法专题】工欲善其事必先利其器—— C++ STL中vector(向量/不定长数组)的常用方法总结
    App 设计技巧
    js判断是否在微信浏览器中打开
    WebApi 跨域
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207783.html
Copyright © 2011-2022 走看看