蓝桥杯 算法训练 单词接龙 超详细

嘿嘿,低产博主又来更新了>︿<

这次是dfs搜索的题,我是看另一个博主写的,自己来归纳一下啦~冲冲冲!!!
参考博客:https://www.cnblogs.com/zbx2000/p/12715400.html

问题概述
1.已知一组单词
2.给定一个开头的字母
3.要求出以这个字母开头的最长的“龙”
4.每个单词都最多在“龙”中出现两次 5.两个单词重合部分合为一部分
6.另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。

#include
#include
#include
using namespace std;
const int N=21;

int n;//单词数
string str[N];//怎么说也要让输入的那些单词有 地方住呀
              //这里的N表示单词数的最多的个数限度
int g[N][N]={0};//两个单词之间能够重合的最短长度
int ans=0;//记录龙的长度
int used[N]={0};//每个单词使用的次数 

void dfs(string dragon,int last)
{
    ans=max((int)dragon.size(),ans);
    //现在龙的长度,强制转换是因为string的size是无符号长整型
    
    used[last]++;//使用次数+1

    //寻找它的下一个单词
    for(int i=0;i<n;i++)
    {
       if(g[last][i]&&used[i]<2)//如果跟第i个单词有重复部分,就接上
         dfs(dragon+str[i].substr(g[last][i]),i);
    }
   used[last]--;
   //我来解释一下大多数blog都没讲到的为什么要恢复现场
   //就好比例子来说,touch是第一个被接上的单词
   //那么这个touch在履行完它接龙的责任之后这个循环就结束了呀
   //本来是要由于递归回到at的让人家at继续挑选看看能不能接上其他重合的单词的另一条龙
   //那么好嘞,你at要接上另一条龙了,就说明龙里面已经不是touch作老二了
   //那你是不是要把人家touch还回去,要用的时候再借嘛
   //ok,就是这样。
}

int main()
{
   cin>>n;
   for(int i=0;i<n;i++)
   cin>>str[i];
   
   char sign;
   cin>>sign;//给定一个开头字母 


   //为了枚举字符串之间相同的字串合并形式
   //必须有预处理出来的字符串之间的相同子串邻接表
   //总不能一遍一遍算吧,得有个表
   for(int i=0;i<n;i++)
   {
      for(int j=0;j<n;j++)//也有可能跟自己egtact
      {
         string a=str[i];//当前的单词
         string b=str[j];//被对照的单词 
         for(int k=1;k<min(a.size(),b.size());k++)
         //不用等于是因为不能是包含关系
         //k表示重复的字串的字符个数
         {
            if(a.substr(a.size()-k)==b.substr(0,k))
            //求最小相同字串才能得出最长的龙
            //重合的越多,龙越短
            {
                 g[i][j]=k;
                 break;
             }
        }
      }
   }

     for(int i=0;i<n;i++)//从第一个单词开始
     {
          if(str[i][0]==sign)
          dfs(str[i],i);
          //第一个参数代表现在的龙的现状
          //第二个参数代表此时操作的单词的坐标
     }

     cout<<ans;
          
     return 0;
     }

   

学会的技巧:

  1. 具有重要意义的统一变量最好写在头文件 下来的地方作为全局变量;
  2. 我今天才用到!!!原来字符串数组我不用再char[][]了!!!!——直接用string str[];
  3. const int 还是很实用的;
  4. 我觉得以后i,j这种局部变量还是不要搞成全局变量比较好,容易乱掉,相信我,要用的时候再设。
  5. substr(i,j)——表示从下标i开始截取j位
  6. substr(i)——表示从i到结尾的字符串
  7. 利用加号直接连接两个字符串常量,会直接把两个字符连接起来

附上一张萨摩美照

你可能感兴趣的:(蓝桥杯,算法训练)