肺炎时节家家闭,提交OJ处处WA
到处都是坑
以下部分“前者”代指目前的龙,“后者”代指现在正在判断的单词
-
重叠的部分越小越好,这样接的龙才长(就是贪心,一开始贪反了。。。)
-
“相邻的两部分不能存在包含关系”其实在一些情况下是可以的,比如两者相同且首尾字母相同时:tact->tact,或者是前者的最后一字母和后者的第一个字母相同时:superbus->super
-
记得同一个单词最多只能接两遍,dfs后记得–vis[i],也就是回溯
-
前者包含后者或者后者包含前者都是可以的,因为是“相邻的两部分不能……”(当然你要判断相邻的两部分不能存在包含关系)
-
后者长度为1时直接跳过,因为对答案不可能有贡献
附代码:
#include<bits/stdc++.h>
using namespace std;
int n;
string s[27];
int vis[27];
int maxn_len;
int max(int x,int y){
if(x>y)return x;
else return y;
}//手写更快
void dfs(string x){
maxn_len=max(maxn_len,x.size());//每次都取一遍大的
for(int i=1;i<=n;++i){
if(s[i].size()==1)continue;//跳过
if(vis[i]>=2)continue;//来过两遍了
int pre=1,minn=min(x.size(),s[i].size());bool flag=false;
for(int j=1;j<=minn;++j){//枚举长度
if(x.substr(x.size()-j,j)==s[i].substr(0,j)){//提取子串
pre=j;flag=true;break;//贪心,即刻退出
}
}
if(!flag)continue;//一次都没找到过
//不加你会找错的,不然就是把pre的初值设为不可能取到的数,然后判断pre的值是否有改变
--pre;//下面用的是下标,所以要--
++vis[i];//来过一次了
string nx=x+s[i].substr(pre+1,s[i].size()-pre-1);//接龙
dfs(nx);
--vis[i];//记得回溯
}
return;
}
int main(){
cin>>n;
for(int i=1;i<=n;++i)cin>>s[i];
string sta;//必须用string,因为dfs里肯定是string(不然你搜完一遍后因为类型不同就结束了)
cin>>sta;
dfs(sta);
cout<<maxn_len;
return 0;
}