dfs | 洛谷 | P1019
阿新 • • 發佈:2019-01-14
https://www.luogu.org/problemnew/solution/P1118
- 用mt函式求每兩個單詞的最小重合部分(越小越好)
- dfs的for內夾緊模式 https://www.cnblogs.com/TQCAI/p/8523035.html
#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
#define F(a,b) for(int a=1;a<=b;a++)
#define LEN 30
using namespace std;
string tr[LEN] ;//儲存字串
int yc[LEN][LEN];//yu chuli 兩個字母的最小重疊部分
int n;
char ch;//開頭字母
int vis[LEN];
int an=0;//每次搜尋到的最長串
int ans=0;
void dfs(int p){//以p編號單詞為尾部
bool jx=false;
F(i,n){ //遍歷所有單詞序列
if(vis[i]>=2) continue;//最多使用兩次
if(yc[p][i]==0) continue;//兩個單詞沒有重合部分
if(yc[p][i]==tr[p].size() ||
yc[ p][i]==tr[i].size()) continue;//有包含關係
an += (tr[i].size()-yc[p][i]);//兩單詞合併再減去最小重合部分
vis[i]++;//使用了一次
jx=true;
dfs(i);
an -= (tr[i].size()-yc[p][i]);//兩單詞合併再減去最小重合部分
vis[i]--;
}
if(jx==false){//說名沒有任何一個單詞可以相連,走到了遞迴盡頭
ans=max(ans,an); //更新ans
}
}
//min together
int mt(int x,int y){ //mt函式, 返回x單詞後y的最小重疊部分
for(int i=tr[x].size()-1;i>=0;i--){//從尾部向前掃描
int iy=0;
bool fd=true;
for(int ix=i;ix<tr[x].size();ix++){
if(tr[x][ix]!=tr[y][iy++]){
fd=false;
break;
}
}
if(fd==true){
return tr[x].size()-i;
}
}
return 0;
}
int main(){
// freopen("./in","r",stdin);
cin>>n;
F(i,n){
cin>>tr[i];
}
cin>>ch;
F(i,n)F(j,n){ //預處理yc
yc[i][j]=mt(i,j);
}
int i=0;
F(i,n){//從頭到尾看一下有沒有指定字母開頭的單詞
if(tr[i][0]==ch){
vis[i]++;
an=tr[i].size();
dfs(i);
vis[i]--;
}
}
cout<<ans;
return 0;
}