题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入
第1行为一个单独的整数n(n≤20),表示单词数,以下n行每行有一个单词,输入的最后1行为一个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出
输出以此字母开头的最长的“龙”的长度。
样例输入
5
at
touch
cheat
choose
tact
a
样例输出
23
提示
样例说明:连成的“龙”为atoucheatactactouchoose。
用len[]计算每个单词的长度,num[]用来计算每个单词出现的次数,string数组s[]用来存储每个单词。
fun(x,y)函数用来寻找单词x与单词y重合的长度:
首先,应先对x倒序与y的首字母比较,找到y的首字母在x里最后一次出现的位置pos
若对于x,没有字母与y的首字母相等或者x的首字母与y的首字母相等(此时,x与y存在包含关系),此时函数返回y的长度。
接着,我们开始检查x中pos位置后的字母与y前面的字母是否相同
若相同,函数返回重复段的长度;否则返回y的长度
solve(i)函数用来进行搜索:
首先,再main函数中,我们对每个单词进行搜索,进入solve函数中,再对每一个单词j进行遍历,遍历的条件:该单词出现的次数小于2
接着,我们在对传入的单词i与遍历的单词j进行比较
定义一个变量p,p=fun(i,j).若 p==len[y] ,则不满足结合的条件;否则,结合i与j,用sum记录此时的长度,再继续往下搜索。
最后用ans存最大的sum,即为所求的答案。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<string> 5 using namespace std; 6 string s[30]; 7 int n,num[30],len[30],ans,sum; 8 char ch; 9 int fun(int x,int y) 10 { 11 int i=len[x]-1,j=0; 12 while(s[x][i]!=s[y][0]) 13 { 14 i--; 15 } 16 if(i<1) 17 return len[y]; 18 while(i<len[x]&&j<len[y]&&s[x][i]==s[y][j]) 19 { 20 i++; 21 j++; 22 } 23 if(i==len[x]&&j<len[y]) 24 return j; 25 return len[y]; 26 27 } 28 void solve(int i) 29 { 30 for(int j=0;j<n;j++) 31 { 32 if(num[j]<2) 33 { 34 num[j]++; 35 int p=fun(i,j); 36 if(p!=len[j]) 37 { 38 sum=sum+len[j]-p; 39 solve(j); 40 sum=sum-(len[j]-p); 41 } 42 num[j]--; 43 } 44 } 45 ans=max(sum,ans); 46 } 47 int main() 48 { 49 cin>>n; 50 for(int i=0;i<n;i++) 51 { 52 cin>>s[i]; 53 len[i]=s[i].size(); 54 } 55 cin>>ch; 56 for(int i=0;i<n;i++) 57 { 58 if(s[i][0]==ch) 59 { 60 num[i]=1; 61 sum=len[i]; 62 solve(i); 63 num[i]=0; 64 sum=0; 65 } 66 } 67 cout<<ans<<endl; 68 }