贤鱼的刷题日常--P1019 [NOIP2000 提高组] 单词接龙--题目详解

今日学习目标:
学习了解P1019 [NOIP2000 提高组]单词接龙–题目详解
✅创作者:贤鱼
⏰预计时间:15分钟
个人主页:贤鱼的个人主页
专栏系列:c++

请添加图片描述

题目

  • 题目要求
    • [NOIP2000 提高组] 单词接龙
      • 题目背景
      • 题目描述
      • 输入格式
      • 输出格式
      • 样例 #1
        • 样例输入 #1
        • 样例输出 #1
      • 提示
  • 思路
  • AC代码

题目要求

[NOIP2000 提高组] 单词接龙

题目背景

注意:本题为上古 NOIP 原题,不保证存在靠谱的做法能通过该数据范围下的所有数据。

题目描述

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

输入格式

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

输出格式

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

样例 #1

样例输入 #1

5
at
touch
cheat
choose
tact
a

样例输出 #1

23

提示

样例解释:连成的“龙”为 atoucheatactactouchoose

n ≤ 20 n \le 20 n20

思路

典型深搜问题
想到深搜不难,问题是怎么搜?
很简单

在搜索的时候,判断两个单词的重叠部分,符合题意就继续搜索,反正时间复杂度不会爆炸其他的就是电脑的任务了

问题是如何判断两个单词的重叠部分

这里我们传两个string类型的字符串a,b
i从0到ab长度较小的一个-1的位置,j从0-i-1的位置
我们只需要从a[-i+j]和b[j]来比较
如果有重合的部分,此时的i就是重合的数量

接下来就搜索就好

AC代码

#include
#include
#include
#include
using namespace std;
int use[20];
int n;
string ch;
int aas=0;
string dc[20];
int xz(string a,string b){
	int len=min(a.length(),b.length());
	for(int i=1;i<len;i++){//按照上面思路处理
		int f=1;//注意要赋值为1
		for(int j=0;j<i;j++)
			if(a[a.length()-i+j]!=b[j]) f=0;
		if(f) return i;
		
	}
	return 0;
}
void dfs(string c,int ans){
	aas=max(aas,ans);
	for(int i=0;i<n;i++){
		if(use[i]>=2) continue;//记录一下使用次数,为什么是等于2呢,因为0,1不就是两次了
		int mm=xz(c,dc[i]);//如果有值说明有重合部分
		if(mm>0){
			use[i]++;
			dfs(dc[i],ans-mm+dc[i].length());//注意,减去重合部分
			use[i]--;
		}
	}
}
int main(){
	cin>>n;
	memset(use,0,sizeof(use));
	for(int i=0;i<n;i++){
		cin>>dc[i];
	}
	cin>>ch;
	dfs(' '+ch,1);//题目要求,不能有包含关系,我们在前面加一个没有意义的字符,就可以避免这个问题
	cout<<aas;

}

你可能感兴趣的:(c++刷题篇,c++,算法,数据结构)