NC16742 [NOIP2002]字串变换

题目链接

题目

题目描述

已知有两个字串 A, B及一组字串变换的规则(至多6个规则):
A1 -> B1
A2 -> B2
规则的含义为:在A中的子串 A1可以变换为 B1、A2可以变换为 B2 …。
例如:A='abcd' B='xyz'
变换规则为:
‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’
则此时,A 可以经过一系列的变换变为 B,其变换的过程为:
‘abcd’->‘xud’->‘xy’->‘xyz’
共进行了三次变换,使得A变换为B。

输入描述

输入格式如下:
A B

A1 B1 \

A2 B2 |-> 变换规则

... ... /

所有字符串长度的上限为 20。

输出描述

输出格式如下:
若在10步(包含 10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"

示例1

输入

abcd xyz
abc xu
ud y
y yz

输出

3

题解

知识点:BFS,字符串。

这道题普通bfs也能过,不过可以用来练练dbfs。从结果和起点同时扩展,如果步数相加超过 \(10\) 说明十步只能无解,否则只要在对方状态里找到自己当前状态再将步数相加返回即可。要注意正向扩展和反向扩展规则是相反的。

要注意的是每步变换不一定只有一次,同一条规则可能用在不同的位置要注意不要漏了。

字符串替换用 string 的成员函数 replace 是真的香2333。

时间复杂度 \(O(?)\)

空间复杂度 \(O(?)\)

代码

#include <bits/stdc++.h>

using namespace std;

vector<pair<string, string>> dir;


int bfs(string init, string ans) {

    map<string, int> vis1, vis2;
    vis1[init] = 0;
    vis2[ans] = 0;

    queue<string> q1, q2;
    q1.push(init);
    q2.push(ans);

    while (!q1.empty() && !q2.empty()) {
        string a = q1.front();
        string b = q2.front();
        q1.pop();
        q2.pop();

        if (vis1[a] + vis2[b] > 10) return -1;///层数都只增不减,两者之和大于10,就算之后找到了也是no answer
        if (vis2.count(a)) return vis1[a] + vis2[a];
        else if (vis1.count(b)) return vis1[b] + vis2[b];
        for (int i = 0;i < dir.size();i++) {
            size_t pos = 0;
            while (~(pos = a.find(dir[i].first, pos))) {
                string aa = a;
                aa.replace(pos, dir[i].first.size(), dir[i].second);
                pos++;
                if (vis1.count(aa)) continue;
                vis1[aa] = vis1[a] + 1;
                q1.push(aa);
            }
        }
        for (int i = 0;i < dir.size();i++) {
            size_t pos = 0;
            while (~(pos = b.find(dir[i].second, pos))) {
                string bb = b;
                bb.replace(pos, dir[i].second.size(), dir[i].first);
                pos++;
                if (vis2.count(bb)) continue;
                vis2[bb] = vis2[b] + 1;
                q2.push(bb);
            }
        }
    }
    return -1;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    string init, ans;
    cin >> init >> ans;

    string a, b;
    while (cin >> a >> b) dir.push_back({ a,b });
    int t = bfs(init, ans);
    if (~t) cout << t << '\n';
    else cout << "NO ANSWER!" << '\n';
    return 0;
}
posted @ 2022-07-16 17:28  空白菌  阅读(116)  评论(0编辑  收藏  举报