信息学奥赛一本通(1220:单词接龙)

 

1220:单词接龙


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 5368     通过数: 3159

【题目描述】

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

【输入】

输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词(只含有大写或小写字母,长度不超过20),输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。

【输出】

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

【输入样例】

5
at
touch
cheat
choose
tact
a

【输出样例】

23

【分析】

        以样例数据为例,构造两两单词接龙重叠字符矩阵,再根据该矩阵构造递归解答树,如下图

        at 可以和 touch 或 tact 相连,长度分为6 或 5,而 touch 则可以和 cheat 或 choose 进行相连,长度为9 或 10,...

        以此类推,最长的龙为:atoucheatactactouchoose。注意:每个单词都最多在“龙”中出现两次。

        这道题用C++代码要简单一些,有关字符串的代码,用C语言非常困难。

感谢题解:https://www.cnblogs.com/-xiangyang/p/9220236.html

【参考代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=50;
string str[MAXN];
int n,used[MAXN];
int ans=0;
int check(string a,string b)//查找想同的部分长度
{
    int la=a.size(),lb=b.size();
    int l=min(la,lb);
    for(int i=1;i<l;i++) {
        int flag = 1;
        for (int j = 0; j < i; j++){
            if(a[la-i+j]!=b[j])
                flag=0;
        }
        if(flag) return i;
    }
    return 0;
}
void dfs(string s,int len)
{
    ans=max(ans,len);
    for(int i=0;i<n;i++){
        if(used[i]>=2) continue;
        int c=check(s,str[i]);
        if(c>0) {
            used[i]++;
            dfs(str[i],len+str[i].size()-c);
            used[i]--;
        }
    }

}
int main()
{
    cin>>n;
    getchar();
    for(int i=0;i<n;i++) {
        cin>>str[i];
        getchar();
        used[i]=0;
    }
    string s;
    cin>>s;
    dfs(' '+s,1);
    cout<<ans<<endl;
    return 0;
}

http://ybt.ssoier.cn:8088/problem_show.php?pid=1220

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值