题意:输入一系列单词,输入一个字母,求出以这个字母开头,由输入单词拼接成的一个最长字符串的长度,每个单词可以出现两次,两个拼接在一起的单词带有重叠部分但是彼此不能有包含关系
这是一道dfs的题目,之前想到dfs, bfs总是自觉的想到一个二维数组找路径之类的问题,刚看这题时完全想不到如何用dfs求解,这道题让我更加了解了dfs搜索的本质,其实和暴力枚举类似,就是地毯式搜索,搜索每一种情况
思路是先对输入数据做一次处理,算出它们每一个单词与其它单词重叠部分的最小长度(因为最后要求拼接成最长的一个单词)
然后遍历每个单词,若首字母为给定字母则开始搜索(若理解不了这里搜索的意思,可以将其看成枚举,多做几道入门经典dfs题目可对其有更深理解)
#include<bits/stdc++.h> using namespace std; int ans; int n; int vis[20]; int cl[20][20]; char c; string words[20]; int commenlength(string a, string b){ int minlen = 50; for(int i=0; i<a.length(); i++){ int m = a.length()-1; int n = i; bool flag = true; while(m>=0 && n>=0){ if(a[m] == b[n]){ m--; n--; }else{ flag = false; break; } } if(flag) minlen = min(i+1, minlen); } return minlen == 50?0 : minlen; } void dfs(int length, int idx){ ans = max(length, ans); for(int i=0; i<n; i++){ if(vis[i] < 2){ if(cl[idx][i] >= 1 && cl[idx][i] != words[idx].length() && cl[idx][i] != words[i].length()){ vis[i]++; dfs(length + words[i].length()-cl[idx][i], i); vis[i]--; } } } } int main(){ ios::sync_with_stdio(false); cin >> n; for(int i=0; i<n; i++) cin >> words[i]; for(int i=0; i<n; i++){ for(int j=0; j<n; j++){ cl[i][j] = commenlength(words[i], words[j]); } } cin >> c; for(int i=0; i<n; i++){ if(words[i][0] == c){ vis[i]++; dfs(words[i].length(), i); vis[i]--; } } cout << ans; return 0; }