(╥╯^╰╥)说起这道题就心酸,几个数据特别坑,几分钟写完的程序花了一个上午调试bug,吐槽完毕,进入正题:
1,需要建立一个标记数组vis表示当前单词被采取的次数;
2,for循环中找到每一个符合条件的龙头,初始化标记数组后进行深度优先搜索;
3,因为连接起来的单词要最长,所以对比是选择从上一个单词的末尾与当前单词的开头进行比对,一旦符合就return
注意!字符相等还不一定符合题意,一定要比到上一个单词的最后一个字符才算符合条件,给出两组数据自己揣摩:
(自己思考后才能有收获吗(~ ̄▽ ̄)~ )
1 2
envelope abababab
e abababc
ans:15 a ans:19下面在代码中进行分析:
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
struct node{
char lin[1000];
}s[20]; // 结构体 s 用于储存单词
int t,ans;
int vis[20]; //标记数组,每一次搜索初始化为 0,单词使用一次加一,超过二就不能继续使用
int len[20]; //单词长度数组,表示每一个单词的长度
int found(int stp,int i){ //stp代表上一个已经选择的单词下标 i表示当前的单词下标
int q,w,j;
for(q=len[stp]-1;q>=1;q--){ //为使长度最长,从上一个单词的末尾开始搜索
if(s[stp].lin[q]==s[i].lin[0]){ //第一个字符匹配后继续看后面还有多少位
int x=0; //相同位数
for(w=q,j=0;w<len[stp]&&j<len[i];w++,j++){
if(s[stp].lin[w]==s[i].lin[j])x++;
else break;
}
if(w==len[stp])return x;//注意!一定要比到上一个字符的最后一个字符答案才有效
}
}
return 0;
}
void dfs(int stp,int length){ //上一个已经选择的单词 当前的最长单词长度
int i;
bool mark=false;
for(i=0;i<t;i++){
if(vis[i]>=2)continue;//单词已经被找过两次,跳过
int x=found(stp,i); //x代表上一个单词与当前单词的匹配位数
if(x!=0){ //匹配位数不为0就继续进行下一次的单词搜索
mark=true;
length+=(len[i]-x); //当前长度增加
vis[i]+=1; //当期单词用过一个加一
dfs(i,length);
//上一步递归不符合题意返回至此,长度减去不符合题意的单词,单词的使用次数减一,继续选择单词
length-=(len[i]-x);
vis[i]-=1;
}
}
if(mark==false){ //如果已经找不到单词,比较之前已经得到过的答案选择最长的单词数
ans=max(ans,length);
}
}
int main(){
int i;
char l1;
cin>>t;
for(i=0;i<t;i++){
cin>>s[i].lin;
len[i]=strlen(s[i].lin);
}
cin>>l1;
ans=0;
for(i=0;i<t;i++)if(s[i].lin[0]==l1){
memset(vis,0,sizeof(vis)); //初始化单词标记数组
vis[i]++; //次单词使用一次
dfs(i,len[i]);//当期使用的单词下标与长度
}
cout<<ans;//输出结果
return 0;
}