CCF201509-3 模板生成系统


题目链接: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);
	}

}

你可能感兴趣的:(CCF201509-3 模板生成系统)