洛谷 P1019 单词接龙

时间:2022-07-26
本文章向大家介绍洛谷 P1019 单词接龙,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目链接

题目描述

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

这道题需要注意三点:

1.每个单词最多在龙里出现两次

2.不能在龙里出现包含关系

3.可以有重合部分

很明显,第一个要接的单词必须首字母是给出的字母,dfs的入口就是满足这个条件的字符串,答案就是这些字符串去dfs找出的最大值,如何dfs?接下来的单词前一部分必须是上一个已经在龙里面的单词的某个后缀,那就去遍历上一个单词从尾开始找,找到一个字符和要接的单词的开头一样,ok接着找,其中一旦发现有某个字符不一样那就不能接龙,如果都可以就返回新增的长度,不如auto,utoh,随便举个例子,找到一个字符和要接的单词一样的位置是u,新增长度是要接的字符长度减去公共长度4-3=1~

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register ll
string s[25];
ll ans,maxx,vis[25],n;
inline ll com(ll x,ll y)
{
    for(rg i=s[x].length()-1;i>=1;i--)
    {
        if(s[x][i]==s[y][0])
        {
            ll ans=0;
            for(rg j=i+1;j<=s[x].length()-1;j++)
            {
                if(s[x][j]!=s[y][++ans])return 0;
            }
            return s[y].length()-ans-1;
        }
    }
    return 0;
}
inline void dfs(ll x)
{
    for(rg i=1;i<=n;i++)
    {
        if(vis[i]<2&&com(x,i))
        {
            ans+=com(x,i);
            vis[i]++;
            dfs(i);//回溯
            vis[i]--;
            ans-=com(x,i);
        }
    }
    //cout<<ans<<endl;
    maxx=max(maxx,ans);
}
int main()
{
    cin>>n;
    for(rg i=1;i<=n;i++)cin>>s[i];
    getchar();
    char ch;
    cin>>ch;
    for(rg i=1;i<=n;i++)
    {
        if(s[i][0]==ch)
        {
            ans=s[i].length();
            vis[i]++;
            dfs(i);
            vis[i]--;
            maxx=max(maxx,ans);
            //cout<<maxx<<endl;
        }
    }
    cout<<maxx<<endl;
    //while(1)getchar();
    return 0;
}