[ USACO 12DEC ] 第一!First!

题述《 https://www.luogu.org/fe/problem/P3065

#include<stdio.h>
char s[30057][357];
int next[300057][29];
int cnt[300057];
int que[300057];
int sz;
int head[29];int adj[300057];int v[300057];int ec;
int indegree[29];
void tinsert(char *s)
{
   int i,j,k;
   j=0;
   for(i=0;s[i];++i)
   {
      k=s[i]-'a'+1;
      if(!next[j][k])
         next[j][k]=++sz;
      j=next[j][k];
   }
   cnt[j]=1;
}
int topos()
{
   int popnow;
   int i,j,k;
   int h=1,t=0;
   for(i=1;i<27;++i)
      if(!indegree[i])
         que[++t]=i;
   while(h<t+1)
   {
      popnow=que[h];
      for(i=head[popnow];i;i=adj[i])
         if(indegree[v[i]])
         {
            --indegree[v[i]];
            if(!indegree[v[i]])
               que[++t]=v[i];
         }
      ++h;
   }
   for(i=1;i<27;++i)
      if(indegree[i])
         return 0;
   return 1;
}
int main()
{
   int N;
   int res[30057];
   int i,j,k,o,p,l,ii;
   scanf("%d",&N);
   i=0;
   do
   {
      ++i;
      scanf("%s",s[i]);
      tinsert(s[i]);
   }while(--N);
   l=0;
   for(p=i,i=1;i<p+1;++i)
   {
      j=0;
      for(ii=0;s[i][ii];++ii)
      {
         k=s[i][ii]-'a'+1;
         if(cnt[j])
            break;
         for(o=1;o<27;++o)
            if(o!=k&&next[j][o])
            {
               v[++ec]=o;
               adj[ec]=head[k];
               head[k]=ec;
               ++indegree[o];
            }
         j=next[j][k];
      }
      if(!s[i][ii])
         if(topos())
            res[++l]=i;
      for(j=0;j<ec+2;++j)
         adj[j]=0;
      for(j=0;j<28;++j)
      {
         indegree[j]=0;
         head[j]=0;
      }
      ec=0;
   }
   printf("%d\n",l);
   for(i=1;i<l+1;++i)
      printf("%s\n",s[res[i]]);
   return 0;
}

允许更改小写字母的字典序,要求找出在可以更改字典序的条件下,字典序第一的模式串(小写模式串)。(考虑模式串 abc 和 abd ,在常规字典序 abcde 的情况下字典序第一的模式串是abc ,现在更改常规字典序为 abdce ,这时 abd 成为了字典序第一的模式串。)

考虑无法使模式串成为字典序第一的模式串的 2 种情况,第一( trie树),存在其他模式串是当前模式串的真前缀,第二(拓扑排序),存在其他模式串和当前模式串有公共前缀,公共前缀的后 1 个字母,其他模式串的要比当前模式串的字典序靠前(考虑模式串 moo 、 mom 和 oc ,我想 moo 成为字典序第一,公共前缀空的时候有 m<o ,公共前缀为 mo 的时候有 o<m ,无法使 moo 成为字典序第一的模式串。)。

算法《 https://wswmsword.github.io/2019/06/21/%E6%8B%93%E6%89%91%E6%8E%92%E5%BA%8F/
算法《 https://wswmsword.github.io/2019/06/01/trie%E5%AD%97%E5%85%B8%E6%A0%91/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值