题目链接:http://115.28.138.223/view.page?gpid=T30
题目为字符串处理,欲将模板中的字符串替换为指定语句,类似于c语言中的#define的实现,但题目中要特别注意一点,模板不递归生成,“也就是说,如果变量的值中包含形如 {{ VAR }} 的内容,不再做进一步的替换”。
若是逐字符处理,则无需考虑递归的问题,可以解决问题。
使用正则表达式可以比较方便的解决这个问题,但是需要注意避免递归生成模板。
可以在原文中找到所有需要替换的内容,前面加前缀Y。在所有变量前面加前缀Y,在题目给的变量内容中可以在被匹配到的内容上加前缀N来避免递归,最后只需删除前缀即可。
即原文中所有的{{ VAR }}变为{{ YVAR }},变量的值中的就变为{{ NVAR }}(好像和部分c++编译器识别重载函数类似吧)
灵活运用正则表达式中的语法回溯引用来简化语法,需要注意的是,回溯引用在各个编程语言中有不同的写法,java中$1匹配第一个括号,以此类推。
这个程序可以得到90分,有些不足。代码是用java实现的,另外c++中也有regex库可以使用。
JAVA语言代码
import java.util.HashMap; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 HashMap<String, String> keys = new HashMap<>();//name-value String text="";//文件内容 int textnum,keysnum;//文件行数,变量数 /*input*/ Scanner scanner = new Scanner(System.in); textnum = scanner.nextInt(); keysnum = scanner.nextInt(); scanner.nextLine(); for(int i=0;i<textnum;i++){ text+=(scanner.nextLine()).replaceAll("\\{\\{ ([_a-zA-Z0-9]+) \\}\\}", "\\{\\{ Y_$1 \\}\\}")+"\n";//防止递归,加前缀Y_,回溯引用 } Pattern name = Pattern.compile("^[_a-zA-Z0-9]+(?=\\s)");//获取变量名字 Pattern context = Pattern.compile("(?<= \").+(?=\")");//获取变量内容 for(int i=0;i<keysnum;i++){ String temp,tname,ttext; temp = scanner.nextLine(); Matcher matcher = name.matcher(temp); if(matcher.find()){ tname = matcher.group(); matcher = context.matcher(temp); if(matcher.find()){ ttext = matcher.group(); }else { ttext = ""; } keys.put("Y_"+tname, ttext.replaceAll("\\{\\{ ([_a-zA-Z0-9]+) \\}\\}", "\\{\\{ N_$1 \\}\\}"));//防止递归,回溯引用,加前缀N_ } } //System.out.println(keys); Pattern pName = Pattern.compile("(?<=\\{\\{ )Y_[_a-zA-Z0-9]+(?= \\}\\})");//获取文中的变量名字 Matcher matcher = pName.matcher(text); while(matcher.find()){ text = text.replaceAll("\\{\\{ "+matcher.group()+" \\}\\}", keys.containsKey(matcher.group())?keys.get(matcher.group()):""); } text = text.replaceAll("\\{\\{ N_([_a-zA-Z0-9]+) \\}\\}", "{{ $1 }}");//回溯引用删除前缀 System.out.println(text); } }