題目描述
單詞接龍是一個與我們經常玩的成語接龍相類似的遊戲,現在我們已知一組單詞,且給定一個開頭的字母,要求出以這個字母開頭的最長的“龍”(每個單詞都最多在“龍”中出現兩次),在兩個單詞相連時,其重合部分合爲一部分,例如 beastbeastbeast和astonishastonishastonish,如果接成一條龍則變爲beastonishbeastonishbeastonish,另外相鄰的兩部分不能存在包含關係,例如atatat 和 atideatideatide 間不能相連。
輸入格式
輸入的第一行爲一個單獨的整數nnn (n≤20n \le 20n≤20)表示單詞數,以下nnn 行每行有一個單詞,輸入的最後一行爲一個單個字符,表示“龍”開頭的字母。你可以假定以此字母開頭的“龍”一定存在.
輸出格式
只需輸出以此字母開頭的最長的“龍”的長度
輸入輸出樣例
輸入 #1
5 at touch cheat choose tact a輸出 #1
23說明/提示
(連成的“龍”爲atoucheatactactouchoose)
NOIp2000提高組第三題
題目大意:讀題吧。
解題思路:需要預處理出每兩個串之間前綴和後綴的公共長度是多少,然後從龍的第一個字母開始搜就可以了。
/* @Author: Top_Spirit @Language: C++ */ #include <bits/stdc++.h> using namespace std ; typedef unsigned long long ull ; typedef long long ll ; const int Maxn = 50; const int INF = 0x3f3f3f3f ; const ull seed = 133 ; const double PI = acos(-1.0) ; int con[Maxn][Maxn] ; int vis[Maxn], ans, n ; string s[Maxn] ,op ; int check(int x, int y){ int len1 = s[x].size() ; int len2 = s[y].size() ; for (int k = 1; k <= min(len1, len2); k++){ int i = len1 - k ; int j = 0 ; bool flag = true ; while (i < len1 && j <= k){ if (s[x][i] != s[y][j]) { flag = false ; break ; } i++ ; j++ ; } if (flag) return k; } return 0 ; } void init(){ for (int i = 1; i <= n; i++){ for (int j = 1; j <= n; j++){ con[i][j] = check(i, j) ; } } } void Dfs(int index, int len){ ans = max(ans, len) ; for (int i = 1; i <= n; i++){ if (vis[i] > 1) continue ; // 每一個單詞只能用兩次 if (con[index][i] == 0) continue ; vis[i]++ ; Dfs(i, len + s[i].size() - con[index][i]) ; vis[i]-- ; } } int main (){ cin >> n ; for (int i = 1; i <= n; i++) cin >> s[i] ; cin >> op ; init() ; for (int i = 1; i <= n; i++){ if (s[i][0] == op[0]){ // 從龍的相同字符開始搜起 vis[i]++ ; Dfs(i, s[i].size()) ; vis[i]-- ; } } cout << ans << endl ; return 0; }