单词接龙

https://www.luogu.org/problemnew/show/P1019  落骨

分3个板块 :

1. 求出两个字符串最小的重复长度

    由题目要求 ,在比较的过程中,一个串不能是另一个串的子串,所以 i != len。 for里面的写法很精妙。。如果找到最小的重复长度,就马上return,输出 ;如果找不到,return 0代表最小重复长度是0;

2. dfs遍历

  如果找到一个s[i] ,不需要和 ans 拼接,只需要把s[i] 接着dfs,找到下一个串就行了。 l 用来记录每次加上s[i] 之后的长度,并且不断更新sum。如果一个串被用了达到2次,就不能用。

3. 输入输出

         这部分重要的是 dfs( ' '+ans , 1 ),感觉无论是' '+ans,还是‘1’都很有意义。。 

  ' '+ans是因为在第一次对ans和别的串进行找 最小的重复长度时,如果不加' ',则 minlen中  x.length() =1,在for中无法运行,最终只能return 0,这个和实际情况肯定是不符的; 加上 ' '之后可以避免这个情况。   

   ( 如果在s[i]中有单个字母的情况,例如 'a',和"ab"在 minlen 中比较时,  '  ' 不加无影响。因为如果这两者有最小重复长度,也是不行的,因为a是 ab的子串,return 0; 如果无最小长度,就return 0;所以无论怎么样都是 return 0的。  这段自动忽略)

    初始 dfs( ' '+ans , 1 )的 ‘1’我还是有点不十分理解。大概是因为  题目要求 一定是存在以 龙头字母为开始的s[i],所以最小长度必须为 1吧 。 

#include<iostream>
#include<cstdio>
#include <cctype>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include<queue>
#include<map>
using namespace std;
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
#define se second
#define fi first
const int INF= 0x3f3f3f3f;
const int N=1e5+5;

int n,sum,vis[30]={0};
string ans, s[25];

int minlen(string x,string y) //最小重合长度
{
    int len=min( x.length(), y.length());
    for(int i=1;i<len;i++) //i!=len  防止是字串
    {
        int flag=0;
        for(int j=0;j<i;j++)
            if( x[ x.length()-i+j] != y[j]) flag=1;
        if(!flag) return i;
    }
    return 0;
}

void dfs(string x, int l) //拼接
{
    sum= max( sum, l);
    for(int i=1;i<=n;i++)
    {
        if( vis[i]>=2 ) continue;

        int mlen = minlen( x, s[i]);
        if( mlen==0) continue;

        vis[i]++;
        dfs(s[i], l+ s[i].length() -mlen);
        vis[i]--;
    }
    return;
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];
    cin>>ans;
    sum=0;//答案
    dfs(' '+ans, 1);

    cout<<sum<<endl;
}
原文地址:https://www.cnblogs.com/thunder-110/p/9372469.html