单词接龙c++题解,请勿抄袭
題目描述
單詞接龍是一個與我們經常玩的成語接龍相類似的游戲,現在我們已知一組單詞,且給定一個開頭的字母,要求出以這個字母開頭的最長的“龍”(每個單詞都最多在“龍”中出現兩次),在兩個單詞相連時,其重合部分合為一部分,例如?beast?和?astonish,如果接成一條龍則變為?beastonish,另外相鄰的兩部分不能存在包含關系,例如?at?和?atide?間不能相連。
輸入格式
輸入的第一行為一個單獨的整數?nn?表示單詞數,以下?nn?行每行有一個單詞,輸入的最后一行為一個單個字符,表示“龍”開頭的字母。你可以假定以此字母開頭的“龍”一定存在。
輸出格式
只需輸出以此字母開頭的最長的“龍”的長度。
輸入輸出樣例
輸入 #1復制
5 at touch cheat choose tact a輸出 #1復制
23說明/提示
樣例解釋:連成的“龍”為?atoucheatactactouchoose。
n \le 20n≤20。
單詞接龍(題解)———hyperbole_Q
基本思路是搜索。
處理的難點在于對重疊部分的處理。
單詞的使用次數很好判斷,開一個數組即可,和正常向dfs的vis數組差不多。
但對于重疊部分的處理,我想細說一下。
因為連接起來的單詞要最長,所以對比是選擇從上一個單詞的末尾與當前單詞的開頭進行比對,如果發現不符那就不能匹配。
其他的代碼解釋都一一使用注釋的方法給各位大神標出來了。如果我講的不夠細或者還有不足,請大神手下留情勿噴,栓Q了。
這里我使用一個check函數,用來比較兩個串s和m的長度為k的接口能不能匹配。
判斷方式有兩種,第一種就是我用的這樣按字符比較,如果發現某處不匹配立即返回false。還有一個方法是用string里面的substr,有興趣的同學可以試一下,如果再繼續拓展的話就大可不必了啊。
我們假設接口長度為k,串s的長度為lens,然后我們從0到k枚舉,判斷s[lens-k+i]是不是等于m[i]。
這個式子怎么來的呢?接口前面的串是s,后面的串是m,那么很顯然,s串的接口最開始應該是lens-k處,然后在后面加上一個枚舉的i就可以保證掃描到所有接口字符(我們的i是從0開始枚舉的)。
還有一些細節問題。 如果我們在接龍的時候發現我們現在要接的龍還不如之前某一次接過的長,那么這個接龍方案肯定不是最優的,所以要舍去,這個正確性是顯然的。
(想一下深搜時的遍歷過程,這句話便不難理解)
使用我這個方法,可能有一個奇怪的想法有同學沒想到,那就是在進行拼接操作時,要注意使用給定的串的副本(即復制一份原來的串)進行拼接處理。
這是因為,如果你把原串改變了,而且這個串還不是最優的,那就完了,回溯不回去了。
具體到操作上,首先,我們從1到n枚舉每個短字符串,如果它已經被用了兩次則continue,然后我們求出當前短串的長度,從1到這個長度枚舉,枚舉的是接口的長度(自然是接口越短融合串越長嘛) 然后執行拼接操作,記錄一下最大長度,再加上回溯就好了。
拼接操作和check函數很像,具體到代碼上大家就能看明白了。廢話不多說,上代碼,保證AC!!!(作者親測)
#include <iostream> #include <cstdio> #include <cstring> #include <string> #define maxn 100//根據題目要求自調,各大網站題目可能會稍有變動 using namespace std; int n; int ans = 0;//其實也不需要賦0,只是個人習慣而已 string word[maxn];//字符串數組,用來存儲單詞 string beginn;//用來存儲開頭字符 int used[maxn];//這個就是用來記錄dfs時候每一個單詞被使用了幾次的數組 bool check(string s,string m,int k){//重點一,check函數判斷接口可行性,k代表接口長度,以下同int lens = s.length();for (int i=0;i<k;i++){if(s[lens-k+i]!=m[i])//我講過了return false;}return true; } void add(string &s,string m,int k){//拼接操作,因為要把m接到s上,所以對于s串不可以傳參,因為我們要試圖改變這個串int lenm = m.length();for (int i=k;i<lenm;i++) s+=m[i];//C++字符串類型特性操作,支持+=符號直接拼接 } void dfs(string now){//這只是一個看似平淡無奇的dfsint x = now.length();ans = max(ans,x);//每次拼接之后更新一下答案for (int i=1;i<=n;i++){if (used[i]>=2)//如果有一個單詞用完了,那這個單詞就不能選了continue;int maxk = word[i].length();for (int j=1;j<=maxk;j++){//枚舉接口長度if (check(now,word[i],j)){string temp = now;//重點二,使用字符串副本進行拼接add(temp,word[i],j);if (temp==now)//拼完之后如果發現長度沒增加,也就是和原串一樣,那這次拼接沒有意義,剪掉continue;used[i]++;dfs(temp);used[i]--;//這只是一個看似平淡無奇的回溯}}} } int main(){cin >> n;for (int i=1;i<=n;i++)cin >> word[i];cin >> beginn;dfs(beginn);cout << ans << endl;return 0; }勿噴,作者只是一個小學生...
總結
以上是生活随笔為你收集整理的单词接龙c++题解,请勿抄袭的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java实现屏幕截屏
- 下一篇: 发售近一周 华为nova2s口碑惊人