Luo Gu problem solution --P1019: word Solitaire

Related topics

Topic Link

Luo Valley, https://www.luogu.com.cn/problem/P1019 .

Total passenger garlic, https://nanti.jisuanke.com/t/T2110 .

Total passenger garlic, https://nanti.jisuanke.com/t/T2152 .

My OJ, http://47.110.135.197/problem.php?id=4209 .

Title Description

Solitaire Solitaire is a word we used to play with the idiom of similar games, and now we know a set of words, and given a letter that begins, requiring the longest "Dragon" (each word beginning with this letter are in most "long" in the appear twice ), when connected to two words, which makes part of the overlapping portions together, and beast Astonish e.g., if connected to the train becomes beastonish, two additional portions adjacent relationship can not exist comprising , and for example, can not be connected between at atide.

Input Format

The first act input a single integer n (n≤20) represents the number of words, the following n lines each have a word, the last act input of a single character, represents the letter "Dragon" at the beginning. You can assume that this begins with the letter "dragon" must exist.

Output Format

Just output begins with this letter the longest "Dragon" in length.

SAMPLE INPUT

5
at
touch
cheat
choose
tact
a

Sample Output

23

Explanation

The longest dragon is atoucheatactactouchoose.

Topic analysis

Analysis of the meaning of problems

At a given point in a word, find the longest dragon. Note that each word appears in a maximum of two times in the Dragon.

For example, the sample data in tact this word, is just the first letter and last letter are t, in accordance with Solitaire rules, it can take your own. 

Sample data analysis

According to our sample data, the relationship can be drawn as shown below:

As shown above, to find the longest word, DFS is a natural process, that is, from the start to write at all possible DFS, the longest that can be found. Meet the requirements of the DFS traversal may be able to find the following:

atoucheatoucheatactact 22

atoucheatouchoose 17

atoucheatactoucheatact 22

atoucheatactouchoose 20

atoucheatactactoucheat 22

atoucheatactactouchoose 23

atouchoose 10

atactoucheatoucheatact 22

atactoucheatouchoose 20

atactoucheatactoucheat 22

atactoucheatactouchoose 23

atactouchoose 13

atactactoucheatoucheat 22

atactactoucheatouchoose 23

atactactouchoose 16

As can be seen above the maximum length of 23.

Algorithm thinking

1, the read data.

2, looking for a leader.

3, structural change relational data.

4, through all the faucet, a faucet with the current DFS, DFS get all possible, find the longest data.

How to determine the word can Solitaire?

Note that the need to find a minimum overlap length. For example, a word to be abababab Solitaire and another word abababab, coincidence character should be two, namely the word ab, Solitaire is ababababababab.

Compare each of violence

This problem due to the small amount of data, n ≤ 20, it is possible to compare the use of violence. I.e. each comparison string and a k-th position of the string b can Solitaire, i.e. to achieve a function as follows:

bool check(const string &a, const string &b, int k)

Generation table

Maintain a relational table. As the picture above, we read in the user data to generate a table. This represents a later description string string b connected to several characters coincide, consider a two-dimensional array will be described. Referring to FIG directed, such as sample input, we can obtain the relationship shown in the following table, the initialization problem to consider, not two words Solitaire represents 0, x> 0 represents the i-th word in the j-th word connected trailing repeated x characters.

word at touch cheat choose tact
at 0 1 0 0 1
touch 0 0 2 2 0
cheat 0 1 0 0 1
choose 0 0 0 0 0
tact 0 1 0 0 1

What does that mean on a table yet? A [i] [j] denotes the i-th string connected behind the j-th character string coincident few. Such a [1] [2] = 2, represents the end of the string touch Cheat To connect string, the repeated characters, the words of Solitaire toucheat, length. 5 (touch length) + 5 (cheat length ) - 2 (overlapped length) = 8.

Code implementation ideas

1, obtaining the i-th and j-th word in the minimum word length, represented by tt.

2, if i == j, is described with a word, then a Save tt. Because they can not

3, an open loop, k 1 from start to finish tt. The i-th word taken from the front of k characters, the j-th word k characters taken from the front backwards, if the same character k, i-described word connected after the j-th of words long, there will be k characters are repeated.

4, after the end of the cycle, determine what containment relationship. If the calculated tt repeated characters and the same size, comprising relationships described.

Code is implemented as follows:

    //找龙头和构建重复字符表
    vector<int> head;
    for (int i=0; i<n; i++) {
        if (ch==word[i].at(0)) {
            head.push_back(i);
        }
        //第i个单词后面接上第j个单词,将重复 k 个字符
        for (int j=0; j<n; j++) {
            int tt = min(word[i].length(), word[j].length());
            string tmp1, tmp2;
            for (int k=1; k<=tt; k++) {
                //word[i]逆序获取
                tmp1 = word[i].substr(word[i].length()-k, k);
                //word[j]正序获取
                tmp2 = word[j].substr(0, k);
                if (tmp1==tmp2) {
                    relation[i][j]=k;
                    break;
                }
            }

            //包含关系
            if (relation[i][j]==tt) {
                relation[i][j]=0;
            }
        }
    }

AC reference code

#include <iostream>
#include <string>
#include <vector>

using namespace std;

const int MAXN = 20+2;
const int MAXUSED = 2;
string word[MAXN];//单词
int used[MAXN];//单词已经使用次数
int relation[MAXN][MAXN];
int sum;//当前龙单词长度
int ans;//最长的长度
int n;//
string dragon; 

//用第 i 个单词开始接龙
void dfs(int i) {
    //标志位,如果发生遍历说明数据构造没有结束
    bool flag = true;
    //遍历
    for (int j=0; j<n; j++) {
        //第 j 个单词没有超过使用限制
        //并且第 j 个单词可以接着第 i 个单词后面
        if (used[j]<MAXUSED && relation[i][j]>0) {
            used[j]++;
            sum += (word[j].length()-relation[i][j]);
            dragon += word[j].substr(relation[i][j], word[j].length()-relation[i][j]);
            dfs(j);
            sum -= (word[j].length()-relation[i][j]);
            used[j]--;
            dragon = dragon.substr(0, dragon.length()-(word[j].length()-relation[i][j]));
            flag = false;
        }
    }

    if (true == flag) {
        //cout << dragon << " " << sum << endl;
        ans = max(ans, sum);
    }
}

int main() {
    cin >> n;
    for (int i=0; i<n; i++) {
        cin>>word[i];
    }
    char ch;
    cin >> ch;

    //找龙头和构建重复字符表
    vector<int> head;
    for (int i=0; i<n; i++) {
        if (ch==word[i].at(0)) {
            head.push_back(i);
        }
        //第i个单词后面接上第j个单词,将重复 k 个字符
        for (int j=0; j<n; j++) {
            int tt = min(word[i].length(), word[j].length());
            string tmp1, tmp2;
            for (int k=1; k<=tt; k++) {
                //word[i]逆序获取
                tmp1 = word[i].substr(word[i].length()-k, k);
                //word[j]正序获取
                tmp2 = word[j].substr(0, k);
                if (tmp1==tmp2) {
                    relation[i][j]=k;
                    break;
                }
            }

            //包含关系
            if (relation[i][j]==tt) {
                relation[i][j]=0;
            }
        }
    }

    int index;
    vector<int>::iterator it;
    for (it=head.begin(); it<head.end(); it++) {
        index = *it;
        used[index]++;
        sum += word[index].length();
        dragon = word[index];
        dfs(index);
        sum -= word[index].length();
        used[index]--;
    }

    cout << ans << endl;

    return 0;
}

 

P.S.

Written explanations report tmd too tired, wrote this report 4+ hours of back and forth, constantly modified algorithm thinking part. Solution to a problem reported in solution to a problem, which is the subject of analysis is the most important, but can not see the code.

Published 235 original articles · won praise 289 · Views 1.07 million +

Guess you like

Origin blog.csdn.net/justidle/article/details/104878323