"""编写一个Python函数,该函数接受两个参数:
一个文本文件【rule】和一个字符串【input】,
请根据文件中【rule】的替换规则返回一个字符串【output】。
def apply_replacement_rules(rules, input_string):
# 你的代码【rule】
解析要求:
1、文本文件【rule】包含按顺序应用的替换规则。
2、每条规则是由空格分隔的两个字符串:s1 s2,其中s1和s2是不包含任何空格字符的字符串。
其含义是:对于输入字符串中的每个子字符串s1,
如果该子字符串没有被之前的任何规则更改过,
则将其替换为s2。
举例:
考虑文件rule.txt的内容如下(包含3条规则):
abc cde
ab b
c a
它在输入字符串babcabdcdc上的工作过程如下:
1.第一条规则:b + cde + abdcdc #abc cde
2.第二条规则:b + cde + b + dcdc #ab b
3.第三条规则:b + cde + b + d + a + d + a #c a
(注意,尽管“cde”包含“c”,但它不会被第三条规则出发,因为它是第一条规则产生的新字符串,而不是来自原始字符串)
所以输出是 bcdebdada
请注意:参数规则【rule】不是固定的, 你的程序应该适用于任何顺序与任何替换规则,
如:c ab
abc cde
ab b
或
abcd ab
cde bcd
ade bc
请你尝试使用最优的时间复杂度来解决这个问题
解题思路:
一、先按行读取rule.txt文件,因其格式固定为每行一条规则,且每行格式为s1 s2,
读取时将其存为字典,该字典rule_dict格式为{n:[s1,s2]},n为行数
二、构造状态字典,用于存储字符串修改的历史状态及当前状态,该状态字典随规则顺序流动而更新。
如:输入字符串babcabdcdc:
1.第一条规则:b + cde + abdcdc #abc cde
此时该字典str_status为:
{1:{"source_str":"babcabdcdc","new_str":"bcdeabdcdc","change_index":["1,3"]}}
字段说明:键1表示第一条规则,键1对应的值表示第一条规则运行后的状态,source_str表示
执行第一条规则之前的输入字符串,new_str表示执行第一条规则之后的输出字符串,change_index"表示
new_str中哪一段索引是被改变的索引
2.第二条规则:b + cde + b + dcdc #ab b
此时该字典str_status为:
{1:{"source_str":"babcabdcdc","new_str":"bcdeabdcdc","change_index":["1,3"]},
2:{"source_str":"bcdeabdcdc","new_str":"bcdebdcdc","change_index":["1,3","4"]},
}
3.第三条规则:b + cde + b + d + a + d + a #c a
此时该字典str_status为:
{1:{"source_str":"babcabdcdc","new_str":"bcdeabdcdc","change_index":["1,2,3"]},
2:{"source_str":"bcdeabdcdc","new_str":"bcdebdcdc","change_index":["1,2,3","4"]},
3:{"source_str":"bcdebdcdc","new_str":"bcdebdada","change_index":["1,2,3","4","6,8"]},
}
三、字符串按规则处理函数
传入rule_dict和原生字符串。按照规则进行处理:对于输入字符串中的每个子字符串s1,
如果该子字符串没有被之前的任何规则更改过(通过str_status判断有没有更改过),则将其替换为s2,
之后更新str_status"""
"""编写一个Python函数,该函数接受两个参数:
一个文本文件【rule】和一个字符串【input】,
请根据文件中【rule】的替换规则返回一个字符串【output】。
def apply_replacement_rules(rules, input_string):
# 你的代码【rule】
解析要求:
1、文本文件【rule】包含按顺序应用的替换规则。
2、每条规则是由空格分隔的两个字符串:s1 s2,其中s1和s2是不包含任何空格字符的字符串。
其含义是:对于输入字符串中的每个子字符串s1,
如果该子字符串没有被之前的任何规则更改过,
则将其替换为s2。
举例:
考虑文件rule.txt的内容如下(包含3条规则):
abc cde
ab b
c a
它在输入字符串babcabdcdc上的工作过程如下:
1.第一条规则:b + cde + abdcdc #abc cde
2.第二条规则:b + cde + b + dcdc #ab b
3.第三条规则:b + cde + b + d + a + d + a #c a
(注意,尽管“cde”包含“c”,但它不会被第三条规则出发,因为它是第一条规则产生的新字符串,而不是来自原始字符串)
所以输出是 bcdebdada
请注意:参数规则【rule】不是固定的, 你的程序应该适用于任何顺序与任何替换规则,
如:c ab
abc cde
ab b
或
abcd ab
cde bcd
ade bc
请你尝试使用最优的时间复杂度来解决这个问题
解题思路:
一、先按行读取rule.txt文件,因其格式固定为每行一条规则,且每行格式为s1 s2,
读取时将其存为字典,该字典rule_dict格式为{n:[s1,s2]},n为行数
二、构造状态字典,用于存储字符串修改的历史状态及当前状态,该状态字典随规则顺序流动而更新。
如:输入字符串babcabdcdc:
1.第一条规则:b + cde + abdcdc #abc cde
此时该字典str_status为:
{1:{"source_str":"babcabdcdc","new_str":"bcdeabdcdc","change_index":["1,3"]}}
字段说明:键1表示第一条规则,键1对应的值表示第一条规则运行后的状态,source_str表示
执行第一条规则之前的输入字符串,new_str表示执行第一条规则之后的输出字符串,change_index"表示
new_str中哪一段索引是被改变的索引
2.第二条规则:b + cde + b + dcdc #ab b
此时该字典str_status为:
{1:{"source_str":"babcabdcdc","new_str":"bcdeabdcdc","change_index":["1,3"]},
2:{"source_str":"bcdeabdcdc","new_str":"bcdebdcdc","change_index":["1,3","4"]},
}
3.第三条规则:b + cde + b + d + a + d + a #c a
此时该字典str_status为:
{1:{"source_str":"babcabdcdc","new_str":"bcdeabdcdc","change_index":["1,2,3"]},
2:{"source_str":"bcdeabdcdc","new_str":"bcdebdcdc","change_index":["1,2,3","4"]},
3:{"source_str":"bcdebdcdc","new_str":"bcdebdada","change_index":["1,2,3","4","6,8"]},
}
三、字符串按规则处理函数
传入rule_dict和原生字符串。按照规则进行处理:对于输入字符串中的每个子字符串s1,
如果该子字符串没有被之前的任何规则更改过(通过str_status判断有没有更改过),则将其替换为s2,
之后更新str_status"""
import re
def read_rules_file(file_path):
rule_dict = {}
if "\n" in file_path:
for n, line in enumerate(file_path.split("\n")):
s1, s2 = line.strip().split()
rule_dict[n] = [s1, s2]
else:
with open(file_path, 'r', encoding='utf-8') as file:
for n, line in enumerate(file, start=1):
s1, s2 = line.strip().split()
rule_dict[n] = [s1, s2]
return rule_dict
def find_substring(main_string, sub_string):
indexes = [m.start() for m in re.finditer('(?={})'.format(re.escape(sub_string)), main_string)]
target_index = []
for index in indexes:
if main_string.find(sub_string) == -1:
return False
else:
target = list(range(index, index + len(sub_string)))
str_target = ",".join(map(str, target))
target_index.append(str_target)
return target_index
def replace_by_indices(input_str, indices_list, replacement):
new_str = list(input_str)
for i, indices in enumerate(indices_list):
#获取起始位置和结束位置
start, end = map(int, [indices.split(',')[0], indices.split(',')[-1]])
#考虑切片长度与要替换的字符串长度不等的情况
len_qie = len(replacement) - (end + 1 - start)
start = start + len_qie * i
end = end + len_qie * i
new_str[start:end + 1] = replacement
return ''.join(new_str)
def parse_number_string(s: str):
"""将连续数字字符串转换为整数列表"""
return [int(n) for n in s.split(',')]
def check_relationship(s1: str, s2: str):
"""
判断两个连续数字字符串是否存在交叉或包含关系。
:param s1: 第一个连续数字字符串
:param s2: 第二个连续数字字符串
:return: 返回关系类型,'none', 'cross', 或 'contain'
"""
# 将字符串转换为整数列表
list1 = parse_number_string(s1)
list2 = parse_number_string(s2)
# 获取每个列表的边界值
min1, max1 = min(list1), max(list1)
min2, max2 = min(list2), max(list2)
# 检查包含关系
if min1 >= min2 and max1 <= max2:
return True
elif min2 >= min1 and max2 <= max1:
return True
# 检查交叉关系
if max1 >= min2 and min1 <= max2:
return True
elif max2 >= min1 and min2 <= max1:
return True
# 如果既不交叉也不包含,返回 'none'
return False
def apply_replacement_rules(rules_file, input_string: str):
rule_dict = read_rules_file(rules_file)
# 规则条数
len_rule_dict = len(rule_dict)
str_status = {}
current_str = input_string
for rule_num, (s1, s2) in rule_dict.items():
if not str_status: # 如果为空,则为第一次规则
# 记录第一条规则执行前的s1的所有位置
before_pro = find_substring(input_string, s1)
if before_pro: # 只有s1存在于input_string中时才考虑替换
current_str = input_string.replace(s1, s2)
if len(s1) == len(s2): # 当s1等于s2的长度时直接替换并更新状态字典
str_status[rule_num] = {
"source_str": input_string,
"new_str": current_str,
"change_index": before_pro
}
else: # 如果不等
len_d = len(s2) - len(s1)
before_pro_new = []
for index_ren, index_replace in enumerate(before_pro):
list_index = index_replace.split(",")
if len_d < 0: # 如果小于
for i in range(abs(len_d)):
list_index.pop(-1)
else: # 如果大于
N_ = 0
for i in range(abs(len_d)):
N_ += 1
list_index.append(str(int(list_index[-1]) + N_ + abs(len_d) * index_ren))
list_index[0] = str(int(list_index[0]) + abs(len_d) * index_ren)
list_index = ",".join(list_index)
before_pro_new.append(list_index)
str_status[rule_num] = {
"source_str": input_string,
"new_str": current_str,
"change_index": before_pro_new
}
else:
# 上次执行规则后的字符串
new_str = str_status[sorted(list(str_status.keys()))[-1]]["new_str"]
# 准备改动的位置
before_pro = find_substring(new_str, s1)
# 准备改动的位置,缓存
before_pro_temp = find_substring(new_str, s1)
# 已经改动的位置
change_index = str_status[sorted(list(str_status.keys()))[-1]]["change_index"]
# 只有s1存在于input_string中时才考虑替换
if before_pro:
# 每一个准备改动的位置
for pre_chage in before_pro_temp:
# 每一个已经改动的位置
for change_part in change_index:
# 如果准备改动的位置与已经改动的位置存在交叉、包含关系
if check_relationship(pre_chage, change_part):
# 将不可改动的位置从准备改动的位置移除
before_pro.pop(before_pro.index(pre_chage))
# 将可以改动的位置按索引进行替换
current_str = replace_by_indices(new_str, before_pro, s2)
# 状态更新
before_pro_new = change_index + before_pro
str_status[rule_num] = {
"source_str": new_str,
"new_str": current_str,
"change_index": before_pro_new
}
return current_str, str_status
# Example usage
'''常规情况'''
# rules_file = "rule.txt"
# rules_file = "abc cde\nab b\nc a"#bcdebdada
# rules_file = "c ab\nabc cde\nab b" # bbabbdabdab
# input_string = "babcabdcdc"
# output_string, status = apply_replacement_rules(rules_file, input_string)
# print("Output String:", output_string)
# print("Status:", status)
'''特殊情况'''
# rules_file = "abcd ab\ncde bcd\nade bc"#babcabdcdc
# input_string = "babcabdcdc"
# output_string, status = apply_replacement_rules(rules_file, input_string)
# print("Output String:", output_string)
# print("Status:", status)
'''自测试'''
# rules_file = "ab aby\ncde bcid\nade bc\nb g" # gabycdabydbcidc
# input_string = "babcdabdcdec"
# output_string, status = apply_replacement_rules(rules_file, input_string)
# print("Output String:", output_string)
# print("Status:", status)
'''问题数据'''
# rules_file = "bcd ac\ncd ba\nab dd\nc a" # ddaddaaacba
# input_string = "abcabcabcdcd"
# output_string, status = apply_replacement_rules(rules_file, input_string)
# print("Output String:", output_string)
# print("Status:", status)