单词接龙 | ||||||
| ||||||
Description | ||||||
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。 | ||||||
Input | ||||||
有多测测试数据。 对于每组测试数据,第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在. | ||||||
Output | ||||||
只需输出以此字母开头的最长的“龙”的长度 | ||||||
Sample Input | ||||||
5 at touch cheat choose tact a | ||||||
Sample Output | ||||||
23 | ||||||
Hint | ||||||
样例中连成的“龙”atoucheatactactouchoose。 | ||||||
Source | ||||||
NOIp2000提高组 | ||||||
Recommend | ||||||
黄李龙 |
解题思路:处理出每两个字符串最少重合的长度,然后dfs
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
string s[25];
int a[25][25];
int n,len[25],ma;
int visit[25];
char ch;
void dfs(int sum,int k)
{
ma=max(ma,sum);
for(int i=1;i<=n;i++)
{
if(visit[i]==2) continue;
if(a[k][i])
{
visit[i]++;
dfs(sum+len[i]-a[k][i],i);
visit[i]--;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
ma=-1;
memset(visit,0,sizeof visit);
for(int i=1;i<=n;i++) cin>>s[i],len[i]=s[i].length();
cin>>ch;
memset(a,0,sizeof a);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int l=len[i]-1,r=0,kk=len[i]-1;
while(1)
{
while(s[i][l]==s[j][r]) l++,r++;
if(r!=len[j]&&l==len[i])
{
a[i][j]=r;
break;
}
kk--,r=0,l=kk;
if(l==0) break;
}
}
}
for(int i=1;i<=n;i++)
{
if(s[i][0]==ch&&len[i]>1)
{
visit[i]++;
dfs(len[i],i);
visit[i]--;
}
}
printf("%d\n",ma);
}
return 0;
}