【题解】洛谷1019 单词接龙 字符串处理+dfs深搜

题目连接:
https://www.luogu.org/problem/P1019c++

题目大意:
①已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”
②每一个单词都最多在“龙”中出现两次
③重合部分合为一部分,且每次取两单词重合部分的最短值
④两单词不能有包含关系web

个人题解:
以给出的输入输出样例为例:数组

输入:
5
at
touch
cheat
choose
tact
a
输出:
23

①首先对要判断的两个字符串进行判断,获得两个字符串链接后,第二个字符串减去重合部分的长度(如at和touch处理后获得4,而at和at处理后为0),由此获得表格:
在这里插入图片描述svg

获得该表格以后就可用DFS深搜一个一个试哪条龙是最长的了spa

按样例的数据解题过程就是:code

在这里插入图片描述

个人代码:xml

#include<bits/stdc++.h>
using namespace std;
string s[50];
char ch;
int cd[50][50];  //cd数组用来记录第二个单词除去重叠部分的值 
int vis[50];  //记录每一个单词使用次数 
int ans, tmp, n;

void count(int a, int b){
	int alen = s[a].length();
	int blen = s[b].length();
	int flag; //flag记录第一个字符串末尾和第二个字符串开头是否有重叠部分 
	int i;
	for(int j=0; j<alen; j++){
		flag = 1;
		for(i=0; i+j<alen&&i<blen; i++){
			if(s[a][i+j] != s[b][i]){
				flag = 0;
				break;
			}
		}
		
		//若是有重叠部分,cd数组记录第二个字符串减去重叠部分的值 
		if(flag) 
			cd[a][b] = blen-i; 
	}	
}

int  dfs(int pos){
	//flag变量记录位置为pos的单词是否还能接下一个单词 
	int flag = 1;  
	
	for(int i=0; i<n; i++){
		if( vis[i]==2 || cd[pos][i]==0 ) continue;
		vis[i]++;
		tmp+=cd[pos][i];
		flag = 0;
		dfs(i);
		tmp-=cd[pos][i];
		vis[i]--;
	}
	
	//若是单词接龙已经结束,记录下长度最大值 
	if(flag)
		ans = max(ans, tmp);
}

int main(){
	
	scanf("%d", &n);
	for(int i=0; i<n; i++){
		cin>>s[i];
	}
	cin>>ch;
	
	//初始化cd数组 
	for(int i=0; i<n; i++){
		for(int j=0; j<n;j ++){
			count(i, j);
		}
	}
	
	ans = tmp = 0;
	
	for(int i=0; i<n; i++){
		if(s[i][0] == ch){
			vis[i]++;
			tmp = s[i].length();
			dfs(i);
			vis[i]--;
		}
	}
	
	printf("%d\n",ans);
}