算法标签:dfs
题目链接:单词接龙
题意:给定m(m<20)个字符串,如果一个字符串是另一个字符串的非平凡后缀,则可以将此字符串连接在另一个字符串的后面,公用重叠的部分,这个新的字符串称之为“龙”,求龙的最长长度,每个字符串可用两次。
思路:由于m<20,所以很容易想到暴搜。
首先,预处理出来所有的连接情况,三层循环即可,前两层表示第j个字符串是否能接在第i个字符串后面,第三层枚举长度,从小到大枚举,因为想要长度最大,公共部分就要最小,而且这样选择并不会影响后面的连接,如果能够连接则直接break,代码如下:
for(int i=0;i<m;i++) { for(int j=0;j<m;j++) { int n1=str[i].size(),n2=str[j].size(); for(int len=1;len<min(n1,n2);len++) { if(str[i].substr(n1-len,len)==str[j].substr(0,len)) { link[i][j]=len; //cout<<str[i]<<" "<<str[j]<<" "<<len<<endl; break; } } } }
link[i][j]=len表示第i个字符串与第j个字符串有公共部分,长度为len。
预处理完后,dfs首字母为所给字母的字符串,结果取max
其中第一个参数表示当前的“龙”,第二个参数表示上一个字符串的下标
完整代码如下:
#include<bits/stdc++.h> using namespace std; #define sf(x) scanf("%lld",&x) #define sff(x,y) scanf("%lld%lld",&x,&y) #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pii pair<int,int> #define f first //#define s second #define int long long const int N=30; string str[N]; int link[N][N],st[N]; int m,res; char sta; void dfs(string s,int now) { res=max(res,(int)s.size()); for(int i=0;i<m;i++) { if(link[now][i]&&st[i]!=2){ st[i]++; dfs(s+str[i].substr(link[now][i]),i); st[i]--; } } } signed main() { sf(m); for(int i=0;i<m;i++) cin>>str[i]; //预处理出来两两之间是否能够连接 for(int i=0;i<m;i++) { for(int j=0;j<m;j++) { int n1=str[i].size(),n2=str[j].size(); for(int len=1;len<min(n1,n2);len++) { if(str[i].substr(n1-len,len)==str[j].substr(0,len)) { link[i][j]=len; //cout<<str[i]<<" "<<str[j]<<" "<<len<<endl; break; } } } } cin>>sta; for(int i=0;i<m;i++) { memset(st,0,sizeof st); if(str[i][0]==sta) st[i]+=1,dfs(str[i],i); } cout<<res; }
Acwing 1117. 单词接龙
最新推荐文章于 2024-06-13 23:07:13 发布