洛谷P1032 字串变换

本文介绍了一种使用广度优先搜索(BFS)算法解决字符串转换问题的方法,目标是在限定次数内将一个字符串转换为另一个字符串。文章详细解释了如何利用BFS遍历所有可能的转换路径,同时避免重复计算和无效状态,以提高算法效率。

题面

给出最多6个 str1->str2 的变换规则,问能否在10次以内将给出的串1变为串2。如能,则输出最少变换次数
字符串长度不超过20

分析

从最少变换次数这里不难想到bfs,结合find查找串中是否有 str1 的可变换串,再用 string的replace方法可以直接得到变换后的串

坑点1:find只会找到一个 str1 并对其做变换,但实际上变换发生的位置可以是多个的,所以每一个节点可到达的状态不止变换规则数量那么多。
例如原串 aaab 在规则 a->c 中通过一次操作可以得到三种串:caab, acab, aacb.这些都要统计入
为了应对这种情况,用 find(string, start_pos)的方法,找到所有 str1 存在的位置即可

p = cur.find(rules[0][i], p + 1);//相当于迭代

坑点2:坑点1会带来大量可能性,不是一秒内能处理的,并且会有很多重复。
所以剪枝,策略是发现对每一个串,都要检查所有的替换规则,所以在不同位置出现的同一个串可到达的情况是相同的,于是舍弃操作次数较多才能出现的该串,只保留第一次(bfs序保证这个串操作次数要小于等于其他相同的串)。这可用hash来完成,这里用map来实现hash,发现已经出现过,则跳过。

代码

#include <stdio.h>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<map>
using namespace std;
int flag = -1;//记录答案
int num = 0;
string ans;
string rules[2][7];
queue<pair<string,int> >q;
map<string, int>m;
void bfs(string str)
{
    q.push(make_pair(str,0));
    int deep,p=0;
    string cur;
    string temp;
    while (!q.empty())
    {
        cur = q.front().first;
        deep = q.front().second;
        q.pop();
        if (cur == ans) { flag = deep;break; }
        if (m.count(cur)==1||deep == 10)continue;//m.count即hash去重
        m[cur] = 1;
        for (int i = 0; i < num; i++)
        {
            p=cur.find(rules[0][i]);
            while (p!=cur.npos)
            {
                temp = cur;
                q.push(make_pair(temp.replace(p, rules[0][i].length(), rules[1][i]), deep + 1));
                p = cur.find(rules[0][i], p + 1);//迭代寻找所有可能替换
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    string raw;
    cin >> raw >> ans;
    while (cin>>rules[0][num])
    {
        cin >> rules[1][num++];
    }
    bfs(raw);
    if (flag != -1)cout << flag;
    else cout << "NO ANSWER!";
    return 0;
}
### P1032 字串变换 Java 实现 针对P1032字串变换问题,在Java中可以通过多种方式实现字符串转换逻辑。下面提供一种基于字符替换的方法,该方法适用于简单的模式匹配和替换场景。 #### 方法概述 此方法遍历源字符串并根据给定规则逐步构建目标字符串。具体来说: - 创建一个新的`StringBuilder`实例用于存储最终的结果。 - 遍历输入字符串中的每一个字符,并应用相应的映射关系将其转换为目标字符。 - 如果遇到特定子串,则按照预设规则进行整体替换而非逐个字符处理。 下面是具体的代码示例: ```java import java.util.HashMap; import java.util.Map; public class StringTransformation { public static void main(String[] args) { Map<String, String> transformationRules = new HashMap<>(); // 建立转换规则表 transformationRules.put("A", "BC"); transformationRules.put("B", "CA"); transformationRules.put("C", "AB"); String sourceString = "ABC"; // 输入原始字符串 int targetLength = 5; // 设定期望长度 System.out.println(transform(sourceString, targetLength)); } private static String transform(String s, int length){ StringBuilder resultBuilder = new StringBuilder(s); while (resultBuilder.length() < length){ for(int i=0 ;i<resultBuilder.length(); ++i){ char currentChar = resultBuilder.charAt(i); if(transformationRules.containsKey(Character.toString(currentChar))){ // 替换当前字符为对应的值 String replacement = transformationRules.get(Character.toString(currentChar)); // 插入新产生的序列至当前位置之后 resultBuilder.insert(i + 1,replacement); // 跳过已经插入的部分继续循环 i += replacement.length(); // 当达到指定长度时提前退出 if(resultBuilder.length() >= length) break; } } } return resultBuilder.substring(0,length).toString(); } } ``` 这段代码展示了如何利用哈希表来管理不同字母之间的对应关系,并通过迭代的方式不断扩展原字符串直到满足所需的总长度为止[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值