https://www.luogu.org/problem/P1019

#include<cstdio> #include<cstring> #include<iostream> using namespace std; char s[50][15]; int check(int x,int y) { for(int i=strlen(s[x])-1;i>=0;i--)//从后往前比,这样能够找到最小的重合 { int j=i; int k=0;//第一个单词x从i往最后比,第二个单词从头开始比 while(s[x][j]==s[y][k]&&j<strlen(s[x])&&k<strlen(s[y]))//如果两个单词的对应位置相同并且都没有出去(过了最大的长度) { j++; k++;//那么都到下一位 } if(j==strlen(s[x]))return strlen(s[x])-i;//如果出来的时候第一个单词已经比完了,就说明可以匹配上了,返回重合的长度 } return 0; } int n; int vis[30]; int ans; int f[105][105]; void dfs(int len,int wz) { for(int i=1;i<=n;i++) { int tmp=f[wz][i];//再次把两个单词之间的连接长度取出 if(vis[i]!=2&&tmp)/如果用了没过两次还能连,就连上试试 { vis[i]++;//用了一次 dfs(len+strlen(s[i])-tmp,i);//长度变成了新连接上的单词的长度减去两个单词重合的长度,龙的最后一个单词变成了i vis[i]--;//恢复现场 } } ans=max(ans,len);//每次都要更新 } void init() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int tmp=check(i,j);//检查两个单词的重合程度 if(tmp&&tmp!=strlen(s[i])&&tmp!=strlen(s[j]))//如果两个单词有重合并且不是一个完全包括了另外一个 { f[i][j]=tmp;//那么就可以记录下来了 } } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s[i]); } init();//预处理,将每两个单词之间能不能接,如果能接,接了多长记录下来 char head; cin>>head;//读入龙头 for(int i=1;i<=n;i++) { if(s[i][0]==head)//如果有一个单词可以接到脖子位置 { vis[i]++;//那么这个单词首先被用了一次 dfs(strlen(s[i]),i);//从脖子长度(包含了头),脖子在零件库s中的位置开始 vis[i]--;//别忘了这里的返回现场也不能疏忽 } } printf("%d\n",ans); return 0; }