洛谷 P1019 单词接龙

题目描述:
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 b e a s t a s t o n i s h ,如果接成一条龙则变为 b e a s t o n i s h ,另外相邻的两部分不能存在包含关系,例如 a t a t i d e 间不能相连。
输入输出格式:
输入:
输入的第一行为一个单独的整数 n (n<20)表示单词数,以下 n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出:
只需输出以此字母开头的最长的“龙”的长度
输入输出样例
输入:

5
at
touch
cheat
choose
tact
a

输出:

23

解题思路:
注意两点即可:
1)计算两个字符串前后的重复片段,并让重复片段尽可能的短。如 a b a b a b a b a b a b a b a b 的重复片段仅记为 a b 两位。
2)其次深搜时注意回溯。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char strs[21][100];
int cnt[21];//初始化时直接为0 
int totalLen=0,n;
int linkLen(char str1[],char str2[]){//求出两个字符串的前后重复片段
    int len1=strlen(str1),len2=strlen(str2);
    for(int i=1;i<len1&&i<len2;i++){
        int flag=1;
        for(int j=0;j<i;j++){
            if(str1[len1-i+j]!=str2[j]){
                flag=0;
                break;
            }
        }
        if(flag)
            return i;
    }
    return 0;
} 

void solve(char str[],int length){
    totalLen=max(length,totalLen);
    for(int i=0;i<n;i++){
        if(cnt[i]>=2)//超过两次
            continue;
        int tmp=linkLen(str,strs[i]);
        if(tmp>0){//含有重复片段
            cnt[i]++;
            solve(strs[i],length+strlen(strs[i])-tmp);
            cnt[i]--;
        }
    }
}

int main(int argc, char** argv) {
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s",strs[i]);
    }
    char st;
    cin>>st;
    for(int i=0;i<n;i++){
        if(strs[i][0]==st){
            cnt[i]++;
            solve(strs[i],strlen(strs[i]));
            cnt[i]--;
        }
    }
    printf("%d\n",totalLen);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhuixun_/article/details/82557718