1913:【00NOIP普及组】单词接龙

文章详细展示了如何使用C++编写程序解决单词接龙问题,通过深度优先搜索和限制单词重复使用次数,计算以特定字母开头的最长单词链。

【题目描述】

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

【输入】

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

【输出】

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

【输入样例】

5
at 
touch
cheat
choose
tact
a

【输出样例】

23

【提示】

样例连成的“龙”为atoucheatactactouchoose

废话不多说,AC代码启动!

#include<bits/stdc++.h>
using namespace std;
#define N 25 
int n, totLen, mxLen;//totLen:龙当前长度 mxLen:龙最大长度 
string s[N];//s[i]:单词列表第i个单词 
int vis[N];//vis[i]:单词s[i]用了几次 
void dfs(string ls)//ls:当前龙中最后字符串 
{
    mxLen = max(totLen, mxLen);//取可能的最大的长度 
    for(int i = 1; i <= n; ++i)
    {
        if(vis[i] < 2)//只要用了不足2次 
        {
            int len;//ls与s[i]重合部分的长度 
            for(len = 1; len < ls.length() && len < s[i].length(); ++len)//由于重合部分不能包含单词,所以重合部分长度要小于两单词的长度 
            {//将ls末尾len个字符截取出来,看和s[i]前len个字符是否相同 
                if(ls.substr(ls.length()-len, len) == s[i].substr(0, len))//只要找到一个可以接上的情况,就不再找了,再找到的不会是最长的龙 
                    break;
            }
            if(len < ls.length() && len < s[i].length())//从上面循环中间跳出,表明s[i]可以接在ls后面。如果不满足该条件,说明循环运行到了最后,没有重合部分。 
            {
                vis[i]++;//s[i]多用了1次 
                totLen += s[i].length() - len;//总长度增加s[i].length() - len
                dfs(s[i]);
                totLen -= s[i].length() - len;//恢复状态 
                vis[i]--; 
            }
        }
    }
}
int main()
{
    char stch;//起始字符 
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> s[i];
    cin >> stch;
    for(int i = 1; i <= n; ++i)
    {
        if(s[i][0] == stch)//如果起始字符和s[i]首字符相同 
        {//以s[i]起始
            vis[i]++; 
            totLen = s[i].length();//当前总长度为s[i]的长度 
            dfs(s[i]);
            vis[i]--;//恢复状态 
        }
    }
    cout<<mxLen;
    return 0;
}

给个关注算是支持我,球球了QAQ

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值