题解 | 单词接龙-牛客假日团队赛9C题

C-单词接龙_牛客假日团队赛9

https://ac.nowcoder.com/acm/contest/1071/C

题目描述

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。

输入描述:

输入的第一行为一个单独的整数n(n ≤ 20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出描述:

只需输出以此字母开头的最长的“龙”的长度

示例1

输入
5
at
touch
cheat
choose
tact
a
输出
23
说明
连成的“龙”为atoucheatactactouchoose

解答

确定算法:乍一看这道题,至少想不到有什么较优的方法,那么怎么办呢?最简单的方法:打暴力!!!可是,又该怎么打暴力呢?一看题目就头疼,如何确定接龙的方法?这是最麻烦的事。那么此时就要用到搜索,因为搜索的本质正是将繁琐的过程简化。这里我们将会使用深度优先搜索求解。
题解方法:
这道题就先想想大概接龙的方法吧:输入→从开始的字符判断有没有能接到的龙→如果有字符串能接到,则接上去→再算出接龙后的长度→找到所有接龙情况中的最大值。
1、输入:没有什么技术含量,就不说了,不过最好要用string来存……
cin>>n;
     for(int i=1;i<=n;i++)
      cin>>str[i];
      cin>>str[n+1];//这里把开始的字符存在了所有字符串的后面一个,也可以换成一个变量
2、从开始字符判断能不能接到龙:  
dfs(str[n+1],1);//初始长度为1
3、如果有字符串能接到,就接上去:用dfs从1到n判断这些字符串能不能接上去(只要看两个字符串有没有重叠部分就可以了),然后再继续递归就可以了。
void dfs(string s,int length_now)//s是之前接好的龙,length_now是当前接龙的总长度
  {
     //do something
      for(int i=1;i<=n;i++)
      {
          if(vis[i]>1) continue;
           else
         {
              int add=check(s,str[i]);//当前字符串与原来字符串的重叠部分的大小
              if(add!=0)//即两个字符串有重叠部分
              {
                 //do something
             }
        }
      }
  }
 4算出接龙后的长度:接龙长度当然是原来龙的长度+现在接上的长度-重合的长度,可以用纸笔验证一下的。
但是怎么知道重合长度呢?这是一个麻烦事。当然我们是不知道重合长度的,所以呢?就先假设一个长度,再看看原先龙的尾巴能不能和这个字符串的头对上,如果能就返回。再考虑以下几个问题:
  • Q:假设重合长度的范围是多少?
  • A:从1到两个字符串中长度最小的一个,否则容易发生数组越界。
  • Q:应该按什么顺序来假设重合长度?
  • A:从1开始不断增大,因为重合长度越小,接出的龙就越长。
  • Q:怎么判断首尾是否一样?
  • A:我们需要依靠一一对应关系。从0开始(因为字符串默认下标是从0开始的)到假设重合长度-1(同理)依次来判断一个字符串的首元素和另一个字符串的尾元素是否相等。那么如果判断首元素的字符串的每一位为b[ j ],那么判断尾元素的字符串的每一位为a[ a.length( ) - i + j ],这可能有点难理解,但是只要多画图就明白了。

  • Q:需要特判吗?
  •  A:需要。分两种情况:一种是没有重合长度,要返回0;另一种是两个字符串中长度最小的长度为1,那样因为循环的问题会直接返回0 。
inline int check(string a,string b)
  {
     int p=min(a.length(),b.length());
     for(int i=1;a.length()==1? i<=p:i<p;i++)
     {
         bool flag=true;
         for(int j=0;j<i;j++)
         {
            if(a[a.length()-i+j]!=b[j])
            {   
                flag=false;
                break;
            }
         }
        if(flag==true) return i;
      }
      return 0;
  }
5、算出所有接龙情况中的最长长度:只要每次递归时不断比较就行了……

Code speaks louder than words!

 #include<iostream>
   #include<cstring>
   #include<cmath>
  using namespace std;
   int n,length=0,vis[1000]={0};string str[1000];
   inline int check(string a,string b)
  {
     int p=min(a.length(),b.length());
       for(int i=1;a.length()==1? i<=p:i<p;i++)
     {
        bool flag=true;
         for(int j=0;j<i;j++)
        {
            if(a[a.length()-i+j]!=b[j])
           {   
               flag=false;
                break;
           }
        }
        if(flag==true) return i;
     }
      return 0;
  }
  void dfs(string s,int length_now)
  {
      length=max(length,length_now);
      for(int i=1;i<=n;i++)
     {
         if(vis[i]>1) continue;
          else
         {
             int add=check(s,str[i]);
              if(add!=0)
             {
                 vis[i]++;
                  dfs(str[i],length_now+str[i].length()-add);
                  vis[i]--;
             }
          }
   }
  
 }
  int main()
  {
      cin>>n;
     for(int i=1;i<=n;i++)
       cin>>str[i];
      cin>>str[n+1];
      dfs(str[n+1],1);
      cout<<length<<endl;
       return 0;
 }


来源:gzr
全部评论

相关推荐

Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
废铁汽车人:秋招真是牛鬼蛇神齐聚一堂
点赞 评论 收藏
分享
评论
4
收藏
分享
牛客网
牛客企业服务