dfs | 洛谷 | P1019

版权声明:本文纯属作者口胡,欢迎转载 https://blog.csdn.net/TQCAI666/article/details/86475720

https://www.luogu.org/problemnew/solution/P1118

  1. 用mt函数求每两个单词的最小重合部分(越小越好)
  2. 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;
}

猜你喜欢

转载自blog.csdn.net/TQCAI666/article/details/86475720