📜  将字符串X转换为Y的最小点击

📅  最后修改于: 2021-04-29 10:37:46             🧑  作者: Mango

给定的3个字符的起始字符串X,精加工的3个字符的字符串Y和禁止字符串数组。任务是找到从X达到Y的最小点击次数。

规则:

  • 3个字符中的每个字符都以循环方式更改,即,每次单击时,您都可以从a到ba到z,并且从未显示禁止字。
  • 如果无法达到Y ,则打印-1 每次单击只能更改一个字母。
  • 每个禁止的字符串具有以下形式:{ “ S1”“ S2”“ S3”}其中每个字符串S i包含该字符的禁止字母。
  • 禁止的字符串= {“ ac”,“ bx”,“ lw”}表示禁止使用单词“ abl”,“ cxw”,“ cbl”,“ abw”,“ cbw”,“ axl”,“ axw”和“ cxl”,并且将永远不会显示。

    注意:如果起始字符串X也是可能的禁止字符组合,则结果也应该为-1。

    方法:

    使用BFS(广度优先搜索)进行某些修改,以绕过禁止的字符串以获得最小的点击次数。

    1. 由于这3个位置中的每个位置都可以包含字母,因此,为了遍历单词状态,请创建尺寸为26 * 26 * 26的3D访问数组。
    2. 要可视化每个受限制的单词,请创建另一个尺寸为26 * 26 * 26的3D数组,以跟踪在遍历中绝不能访问的单词。
    3. 由于3个字符中的每个字符都以循环方式更改,即,每次单击时字母将以循环方式更改,因此,每次到达下一个字母时,都需要注意对26取模。
    4. 令单词的当前状态为[XYZ] 。然后,只需单击一下,便可以移动到以下6个状态:
    5. 因此,创建3个实用程序数组dx,dy,dz,以使遍历过程简化。将每个单词状态存储在一个结构中,该结构具有4个字段,即a,b,c(三个字符的每个)和距起始单词的距离。

    下面是上述方法的实现:

    C++
    // C++ code for above program.
    #include 
    using namespace std;
    #define int long long int
      
    // each node represents a word state
    struct node {
        int a, b, c;
        // dist from starting word X
        int dist;
    };
      
    // 3D visited array
    bool visited[26][26][26];
      
    // 3D restricted array
    bool restricted[26][26][26];
      
    // utility arrays for single step
    // traversal in left and right
    int dx[6] = { 1, -1, 0, 0, 0, 0 };
    int dy[6] = { 0, 0, 1, -1, 0, 0 };
    int dz[6] = { 0, 0, 0, 0, 1, -1 };
      
    // function to find the
    // minimum clicks.
    void solve(string start,
               string end, int qx,
               const vector >& forbidden)
    {
      
        memset(visited, 0,
               sizeof(visited));
        memset(restricted, 0,
               sizeof(restricted));
      
        for (auto vec : forbidden) {
      
            string a = vec[0];
            string b = vec[1];
            string c = vec[2];
      
            for (auto x : a)
                for (auto y : b)
                    for (auto z : c) {
      
                        // each invalid word is
                        // decoded and marked as
                        // restricted = true.
                        restricted[x - 'a']
                                  [y - 'a']
                                  [z - 'a']
                            = true;
                    }
        }
      
        // starting and ending letter a
        int sa = start[0] - 'a';
        int ea = end[0] - 'a';
      
        // starting and ending letter b
        int sb = start[1] - 'a';
        int eb = end[1] - 'a';
      
        // starting and ending letter c
        int sc = start[2] - 'a';
        int ec = end[2] - 'a';
      
        if (restricted[sa][sb][sc]
            or restricted[ea][eb][ec]) {
      
            // check if starting word
            // or finishing word is
            // restricted or not
            cout << -1 << endl;
      
            return;
        }
      
        // queue of nodes for BFS
        queue q;
      
        // initial starting word pushed in
        // queue. dist = 0 for starting word
        q.push({ sa, sb, sc, 0 });
      
        // mark as visited
        visited[sa][sb][sc] = true;
      
        while (!q.empty()) {
            node x = q.front();
            q.pop();
      
            // final destination reached condition
            if (x.a == (end[0] - 'a')
                and x.b == (end[1] - 'a')
                and x.c == (end[2] - 'a')) {
      
                cout << x.dist
                     << endl;
                return;
            }
      
            int DIST = x.dist;
            for (int i = 0; i < 6; i++) {
      
                // mod 26 for circular letter sequence
      
                // next letter for a
                int A = (x.a + dx[i] + 26) % 26;
      
                // next letter for b
                int B = (x.b + dy[i] + 26) % 26;
      
                // next letter for c
                int C = (x.c + dz[i] + 26) % 26;
      
                if (!restricted[A][B][C]
                    and !visited[A][B][C]) {
      
                    // if a valid word state,
                    // push into queue
                    q.push({ A, B, C, DIST + 1 });
                    visited[A][B][C] = true;
                }
            }
        }
      
        // reach here if not possible
        // to reach final word Y
        cout << -1 << endl;
    }
      
    // Driver Code
    signed main()
    {
        // starting string
        string X = "znw";
      
        // final string
        string Y = "lof";
      
        // no of restricting word vectors
        int N = 4;
      
        vector > forbidden
            = { { "qlb", "jcm", "mhoq" },
                { "azn", "piy", "vj" },
                { "by", "oy", "ubo" },
                { "jqm", "f", "ej" } };
      
        solve(X, Y, N, forbidden);
        return 0;
    }


    输出:
    22
    


    时间复杂度: O(26 * 26 * 26),因为最大时可以有26 * 26 * 26个字状态。
    空间复杂度: O(26 * 26 * 26)