您的位置:首页 > 其它

蓝桥杯 算法训练 单词接龙 By Assassin [搜索水题]

2017-03-18 11:32 239 查看
问题描述

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

输入格式

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

输出格式

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

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


题目很是简单,字符串也不长不用KMP去匹配,直接暴力匹配一下,最多就是20*20*20*串长度 的规模,提前将字符串i 和 字符串j是否可以连在一起(有序),并且连在一起的重合长度最少是多少(因为要串最长,肯定是要匹配的越短越好,用length[i][j]记录,有序),并且用vector数组记录一下尾部可以链接的串的id,相当于搜索的剪枝吧。用v[i]表示使用的次数,注意不能超过两次。

然后直接看代码~

#include<bits/stdc++.h>
using namespace std;
int n;
string s[21],head;
vector<int>vec[21];
int length[21][21]={0};
int ans=0;
int v[21]={0};

void get_ready(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=s[i].size()-1;k++){
string tmp1,tmp2;
tmp1.assign(s[i],s[i].size()-k,k);
if(s[j].size()<=k) break;
tmp2.assign(s[j],0,k);
if(tmp1==tmp2){
vec[i].push_back(j);
length[i][j]=k;
break;
}
}
}
}
}

void dfs(int pos,int len){
int flag=0;     //用来标记是不是走到了尽头
for(int i=0;i<vec[pos].size();i++){
if(v[vec[pos][i]]<2){
v[vec[pos][i]]++;
flag=1;
dfs(vec[pos][i],len+s[vec[pos][i]].size()-length[pos][vec[pos][i]]);
v[vec[pos][i]]--;
}
}
if(flag==0){
ans=max(ans,len);
return ;
}
}

int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>s[i];
}
cin>>head;
get_ready();
for(int i=1;i<=n;i++){
if(head[0]==s[i][0]){
v[i]++;
dfs(i,s[i].size());
v[i]--;
}
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: