单词接龙 python_[蓝桥杯][算法训练VIP]单词接龙 (C++代码)

本文介绍了Python实现单词接龙的解题思路和代码。通过预处理计算单词间最小重叠部分,然后使用深度优先搜索策略寻找符合条件的单词序列。需要注意的是,相邻单词不能有包含关系,每个单词最多出现两次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解题思路:

注意事项:

参考代码:

首先在题意上可能有些误解。

两个单词合并时,合并部分取的是最小重叠部分

相邻的两部分不能存在包含关系就是说如果存在包含关系,就不能标记为使用过。

每个单词最多出现两次.

(其实也就是读题问题。这些都是我所犯的错误,希望大家能注意一下)

好了。然后是解题思路。

首先是预处理,用yc[i][j]来存储 第i个单词 后连接 第j个单词 的 最小重叠部分(mt函数)

后来预处理完了之后就是深搜:

先从第一个到最后一个单词看一看哪个单词是指定字母为开头的,作为深搜的第一个单词,同时标记使用过一次(vis[i]++)

然后继续搜吧。

以下是代码。 mt函数可能有点难理解。拿草纸模拟一下就能很直观知道在干什么了。#include

#include

#include

#include

using namespace std;int n;//单词数

string tr[30];//存储字符串

int yc[30][30];//两个字母的最小重叠部分

int vis[30];//判断单词使用频率.

int mt(int x, int y){//mt函数,返回x单词后连接一个y单词的最小重叠部分

bool pp=true;

int ky=0;

for(int k=tr[x].size()-1;k>=0;k--){//从x单词尾部向前看看最小重叠部分是从哪里开始的,以为因为是倒着来,所以保证是最小的

for(int kx=k;kx

if(tr[x][kx]!=tr[y][ky++]){

pp=false;                break;

}

}        if(pp==true){//如果说当前以k为开头的前一个单词后缀 ,是后面单词的前缀,就马上返回重叠部分。(tr[x].size()-k是找出来的规律)

return tr[x].size()-k;        }

ky=0;

pp=true;//不行就继续

}    return 0;

}//可能这里有点难理解。可以手动模拟一下char ch;//开头字母 int ans=-1;//答案 int an=0;//每次搜到的当前最长串 void dfs(int p){//p为尾部单词编号(p的后缀就是“龙”的后缀,因为p已经连接到”龙“后面了)

bool jx=false;

for(int j=1;j<=n;j++){

if(vis[j]>=2) continue;//使用了两次就跳过

if(yc[p][j]==0) continue;//两单词之间没有重合部分就跳过

if(yc[p][j]==tr[p].size() || yc[p][j]==tr[j].size()) continue;//两者存在包含关系就跳过

an+=tr[j].size()-yc[p][j];//两单词合并再减去最小重合部分

vis[j]++;//使用了一次

jx=true;//标记一下当前已经成功匹配到一个可以连接的部分

dfs(j); //接上去

an-=tr[j].size()-yc[p][j];//回溯,就要再减回去那一部分长度

vis[j]--;//回溯,使用--

}    if(jx==false){//jx==false说明不能再找到任何一个单词可以相连了

ans=max(ans,an);//更新ans

}    return;

}

int main(){

scanf("%d",&n);

for(int i=1;i<=n;i++)

cin>>tr[i];

cin>>ch;

for(int i=1;i<=n;i++){

for(int j=1;j<=n;j++){

yc[i][j]=mt(i,j);

}

}//预处理yc数组。yc[i][j]就表示,i单词后连接一个j单词的最小重叠部分

//比如 i表示at,j表示att. yc[i][j]就为2 但是yc[j][i]就为0.

//预处理是一个关键

for(int i=1;i<=n;i++){//从头到尾看一下有没有以指定开头字母为开头的单词

if(tr[i][0]==ch){//如果有,就以当前单词为基准进行搜索。

vis[i]++;//使用过一次

an=tr[i].size();//更新当前串长度

dfs(i);//接上

vis[i]=0;//消除影响

}

}

printf("%d",ans);

return 0;

}

其实我自己提交不使用这段代码的,过几天我会把那段代码发上去!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值