题目

单词具体是什么不重要,知道单词间如何转化即可


【分析】

先理清一下题意:

  1. \(n\)个单词,每个单词限用两次
  2. 上一个单词能与下一个单词接上,当且仅当上一个单词的末尾 \(k\) 个字符与下一个单词开头的 \(k\) 个字符完全相同
  3. 给定开头,求最长字符串的长度

我们可以发现,如果我们知道每个单词上一个单词能接哪些单词、下一个单词能接哪些单词、单词的长度,我们接下来的问题都与单词没关系了

同时,假设有两个单词 \(W_1\) 与 \(W_2\),长度分别为 \(L_1,L_2\) ,它们之间的公共部分的长度可以是 \(a_1\ ,\ a_2\ ,\ a_3\dots a_m(a_1<a_2<a_3<\dots<a_m)\)

我们要使得总字符串最长,即需要令 \(W_1\) 与 \(W_2\) 的接龙最长

因为它们接龙的长度为 \((L_1+L_2-a_i),1\leq i\leq m\)

所以我们一定要选择最小的 \(a_1\) ,这样才能保证接龙最长


用 \(Len_i\) 表示单词 \(i\) 的长度, \(App_i\) 表示单词 \(i\) 的出现次数

用 \(Con_{i,j}\) 表示单词 \(i\) 后接单词 \(j\) 时它们的最短公共长度

当然,当 \(Con_{i,j}=0\) 时表示单词 \(i\) 后接单词 \(j\) 的最短公共长度为 \(0\) ,即没有公共部分,那么当然 \(i\) 不能后接 \(j\)

我们可以用 string 类来储存各个单词,毕竟 string 作为“合法公民”,可以直接用 “==” 比较是否相同

设我们用 string 类 \(s_i\) 表示第 \(i\) 个单词

根据 string 的自带函数即可轻松完成 \(Len_i,Con_{i,j}\) 的统计:

//统计 Len[i]
for(register int i=1;i<=N;i++) Len[i]=s[i].size();
//统计 Con[i][j]
for(register int i=1,I=d_N;i<=I;i++)//枚举第一个单词
for(register int j=1,J=d_N;j<=J;j++)//枚举第二个单词
for(register int k=1,K=Min(ar_d_Len[i],ar_d_Len[j]),k<=K;k++)//枚举公共长度
if ( s[i].substr(ar_d_Len[i]-k,k)==s[j].substr(0,k) ){
mt_d_Con[i][j]=k;
break;
//第一次找到的公共长度一定最短
} //s.substr(p,l) 表示截取 s ,从第 p 个变量开始的 l 个字符,的字串,返回值为一个 string 变量

开头怎么处理?

很简单,开头视为单词 \(s_0\),照常处理, \(App_0\) 标记为 \(1\) ,代表只能用 \(1\) 次即可

最后,我们深搜的时候直接从 \(s_0\) 开始

每次根据当前第 \(i\) 个单词,枚举 \(Con_{i,j}\neq 0\) 的单词 \(j\) ,长度增加 \((Len_j-Con_{i,j})\) 即可


【代码】

那本蒟蒻就放 我码风极丑的 代码了

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
using namespace std;
#define f(a,b,c,d) for(register int a=b,c=d;a<=c;a++)
#define g(a,b,c,d) for(register int a=b,c=d;a>=c;a--)
typedef int i32;
typedef unsigned int u32;
typedef long long int i64;
typedef unsigned long long int u64; inline i32 Min(i32 a,i32 b) { return (a<b)?a:b; }
inline i32 Max(i32 a,i32 b) { return (a>b)?a:b; } i32 d_N,ar_d_App[32]={0},ar_d_Len[32]={0},mt_d_Con[32][32]={0}; inline bool alw(char c) { return (c!='\n')&&(c!='\r'); } inline void getstring(string &s){
string t;
getline(cin,t);
if( !alw(t[ t.size()-1 ]) ) s=t.substr(0, t.size()-1 );
else s=t;
} inline i32 input(){
scanf("%d\n",&d_N);
string s[32];
f(i,1,I,d_N) getstring(s[i]);
getstring(s[0]); f(i,0,I,d_N) ar_d_Len[i]=s[i].size(); //i->j
f(i,0,I,d_N)
f(j,1,J,d_N)
f(k,1,K,Min(ar_d_Len[i],ar_d_Len[j]))
if ( s[i].substr(ar_d_Len[i]-k,k)==s[j].substr(0,k) ){
mt_d_Con[i][j]=k;
break;
} ar_d_App[0]=1;
return s[0].size();
} i32 dfs(i32 d_P){
ar_d_App[d_P]++;
i32 d_Ans=0;
f(i,1,I,d_N) if(mt_d_Con[d_P][i]>0&&ar_d_App[i]<2){
i32 d_Tmp=dfs(i)+ar_d_Len[i]-mt_d_Con[d_P][i];
d_Ans=Max(d_Ans,d_Tmp);
}
ar_d_App[d_P]--;
return d_Ans;
} int main(){
i32 d_Ans=input();
cout<<dfs(0)+d_Ans;
return 0;
}

最后安利一下 本蒟蒻的博客

题解 P1019 【单词接龙】的更多相关文章

  1. 洛谷 P1019 单词接龙【经典DFS,温习搜索】

    P1019 单词接龙 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在 ...

  2. P1019 单词接龙

    单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一 ...

  3. 洛谷 P1019 单词接龙 Label:dfs

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  4. 洛谷 p1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  5. P1019 单词接龙 字符串回溯

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  6. (洛谷)P1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的"龙"(每个单词都最多在"龙" ...

  7. 洛谷 P1019 单词接龙 (DFS)

    题目传送门 当时一看到这题,蒟蒻的我还以为是DP,结果发现标签是搜索-- 这道题的难点在于思路和预处理,真正的搜索实现起来并不难.我们可以用一个贪心的思路,开一个dic数组记录每个单词的最小重复部分, ...

  8. 【搜索】P1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  9. [NOIP2000] 提高组 洛谷P1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  10. 洛谷——P1019 单词接龙(NOIP2000 T3)

    https://www.luogu.org/problem/show?pid=1019#sub 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母, ...

随机推荐

  1. css3的伪(伪类和伪元素)大合集

    本文讲css3的伪,不是讲它有多虚伪,而是说它的伪元素样式.不得不说以前虽知html伪元素,但很少用,后得知借助css3伪元素可以发挥极大的便利.故总结css3的伪如下: CSS中存在一些比较特殊的属 ...

  2. Educational Codeforces Round 63 选做

    D. Beautiful Array 题意 给你一个长度为 \(n\) 的序列.你可以选择至多一个子段,将该子段所有数乘上给定常数 \(x\) .求操作后最大的最大子段和. 题解 考虑最大子段和的子段 ...

  3. CheckBox标签和属性

    CheckBox的作用:可以提供复选 下面是我点击按钮查看所选内容的代码:定义按钮监听器,并在onClick方法中调用shoeAlt方法(此方法会在第二块代码定义) Button btn=(Butto ...

  4. UVA - 11186 Circum Triangle (几何)

    题意:有N个点,分布于一个圆心在原点的圆的边缘上,问所形成的所有三角形面积之和. 分析: 1.sin的内部实现是泰勒展开式,复杂度较高,所以需预处理. 2.求出每两点的距离以及该边所在弧所对应的圆周角 ...

  5. HDU - 1394 Minimum Inversion Number(线段树求逆序数---点修改)

    题意:给定一个序列,求分别将前m个数移到序列最后所得到的序列中,最小的逆序数. 分析:m范围为1~n,可得n个序列,求n个序列中最小的逆序数. 1.将序列从头到尾扫一遍,用query求每个数字之前有多 ...

  6. Linux 安装gcc g++

    Linux版本: cat /proc/version Linux version 3.10.0-693.11.6.el7.x86_64 (mockbuild@x86-041.build.eng.bos ...

  7. JPA#ManyToMany

    多对多,多个学生选了多个课程. 涉及到的注解(注解的使用看注释):ManyToManyJoinTableJsonIgnoreProperties @Entity @Table(name = " ...

  8. Centos7.4 kafka集群安装与kafka-eagle1.3.9的安装

    Centos7.4 kafka集群安装与kafka-eagle1.3.9的安装 集群规划: hostname Zookeeper Kafka kafka-eagle kafka01 √ √ √ kaf ...

  9. 实验吧-隐写-FIVE1、so beautiful so white(文件头修改)

    FIVE1 下载图片,kali下foremost恢复文件,将得到的图片用Winhex打开进行观察,发现最后面有一段貌似是代码的东西. LS0uLi4gIC4tICAuLi4uLiAgLS0uLi4gI ...

  10. vue使用Vant UI中的swiper组件及传值

    子组件SwiperBanner <!-- --> <template> <div class="swiper"> <van-swipe : ...