1. 程式人生 > >CCF201703 Markdown(JAVA)

CCF201703 Markdown(JAVA)

問題描述:

問題描述

  Markdown 是一種很流行的輕量級標記語言(lightweight markup language),廣泛用於撰寫帶格式的文件。例如以下這段文字就是用 Markdown 的語法寫成的:



  這些用 Markdown 寫成的文字,儘管本身是純文字格式,然而讀者可以很容易地看出它的文件結構。同時,還有很多工具可以自動把 Markdown 文字轉換成 HTML 甚至 Word、PDF 等格式,取得更好的排版效果。例如上面這段文字通過轉化得到的 HTML 程式碼如下所示:



  本題要求由你來編寫一個 Markdown 的轉換工具,完成 Markdown 文字到 HTML 程式碼的轉換工作。簡化起見,本題定義的 Markdown 語法規則和轉換規則描述如下:
  ●區塊

:區塊是文件的頂級結構。本題的 Markdown 語法有 3 種區塊格式。在輸入中,相鄰兩個區塊之間用一個或多個空行分隔。輸出時刪除所有分隔區塊的空行。
  ○段落:一般情況下,連續多行輸入構成一個段落。段落的轉換規則是在段落的第一行行首插入 `<p>`,在最後一行行末插入 `</p>`。
  ○標題:每個標題區塊只有一行,由若干個 `#` 開頭,接著一個或多個空格,然後是標題內容,直到行末。`#` 的個數決定了標題的等級。轉換時,`# Heading` 轉換為 `<h1>Heading</h1>`,`## Heading` 轉換為 `<h2>Heading</h2>`,以此類推。標題等級最深為 6。
  ○無序列表:無序列表由若干行組成,每行由 `*` 開頭,接著一個或多個空格,然後是列表專案的文字,直到行末。轉換時,在最開始插入一行 `<ul>`,最後插入一行 `</ul>`;對於每行,`* Item` 轉換為 `<li>Item</li>`。本題中的無序列表只有一層,不會出現縮排的情況。
  ●行內:對於區塊中的內容,有以下兩種行內結構。
  ○強調:`_Text_` 轉換為 `<em>Text</em>`。強調不會出現巢狀,每行中 `_` 的個數一定是偶數,且不會連續相鄰。注意 `_Text_` 的前後不一定是空格字元。
  ○超級連結:`[Text](Link)` 轉換為 `<a href="Link">Text</a>`。超級連結和強調可以相互巢狀,但每種格式不會超過一層。

輸入格式

  輸入由若干行組成,表示一個用本題規定的 Markdown 語法撰寫的文件。

輸出格式

  輸出由若干行組成,表示輸入的 Markdown 文件轉換成產生的 HTML 程式碼。

樣例輸入

# Hello

Hello, world!

樣例輸出

<h1>Hello</h1>
<p>Hello, world!</p>

評測用例規模與約定

  本題的測試點滿足以下條件:
  ●本題每個測試點的輸入資料所包含的行數都不超過100,每行字元的個數(包括行末換行符)都不超過100。
  ●除了換行符之外,所有字元都是 ASCII 碼 32 至 126 的可列印字元。
  ●每行行首和行末都不會出現空格字元。
  ●輸入資料除了 Markdown 語法所需,內容中不會出現 `#`、`*`、`_`、`[`、`]`、`(`、`)`、`<`、`>`、`&` 這些字元。
  ●所有測試點均符合題目所規定的 Markdown 語法,你的程式不需要考慮語法錯誤的情況。
  每個測試點包含的語法規則如下表所示,其中“√”表示包含,“×”表示不包含。
測試點編號 段落 標題 無序列表 強調 超級連結
1 × × × ×
2 × × ×
3 × × ×
4 × × ×
5 × × ×
6 × ×
7 × ×
8 × ×
9 × ×
10

提示

  由於本題要將輸入資料當做一個文字檔案來處理,要逐行讀取直到檔案結束,C/C++、Java 語言的使用者可以參考以下程式碼片段來讀取輸入內容。


解題思路:採用集合巢狀的方式來對資料進行儲存。

對於角色屬性:外層採用HashMap集合的方式,將對應角色的名稱作為鍵,再巢狀一個HashMap作為值儲存相應的許可權及等級(許可權名為鍵,許可權等級為值)。

對於使用者屬性 :與角色屬性結構相似,外層用對應角色名稱作為鍵,內層複製其擁有的角色的最高階許可權名稱與等級。

對於查詢:優先判斷許可權,角色,使用者是否存在,然後判斷許可權本身是否分級,查詢需求是否分級,從儲存的使用者HashMap中按照許可權名稱查詢該許可權即可。

易錯點:角色屬性可能擁有兩個相同的名稱而等級不同的許可權,應取等級最高值

 

package permissionQuery;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
	//儲存許可權各型別名稱及最高層級
	public static Map<String, Integer> perm=new HashMap<>();
	//儲存該角色名及所擁有許可權及最高等級
	public static Map<String,HashMap<String,Integer>> roles=new HashMap<>();
	//儲存該使用者名稱及所擁有許可權及最高等級
	public static Map<String,HashMap<String,Integer>> users=new HashMap<>();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		
		int p=sc.nextInt();//許可權型別數目
		for(int i=0;i<p;i++)
		{
			String[] temp=sc.next().split(":");
			if(temp.length==1)
				perm.put(temp[0],-1);//無許可權等級則設為-1
			else
				perm.put(temp[0],Integer.valueOf(temp[1]));
		}
		
		int r=sc.nextInt();//角色型別數目
		for(int i=0;i<r;i++)
		{
			//儲存該角色所擁有的許可權名稱及許可權最高等級
			HashMap<String,Integer> perms=new HashMap<>();
			String roleName=sc.next();//角色名稱
			int permsNum=sc.nextInt();
			for(int t=0;t<permsNum;t++)
			{
				String[] temp=sc.next().split(":");//temp2下標0許可權名,下標1該許可權等級
				if(temp.length==1)//判斷許可權是否含有等級
					perms.put(temp[0],-1);//許可權名,該許可權等級,無等級為-1
				else
				{
					if(perms.containsKey(temp[0]))//若存在該許可權則取該許可權的最高等級進行儲存
					{
						if(perms.get(temp[0])<Integer.valueOf(temp[1]))//比較許可權等級大小
							perms.put(temp[0], Integer.valueOf(temp[1]));
					}
					else
						perms.put(temp[0], Integer.valueOf(temp[1]));
				}
			}
			roles.put(roleName, perms);
		}
		
		int u=sc.nextInt();//使用者數目
		for(int i=0;i<u;i++)
		{
			String userName=sc.next();//使用者名稱稱
			//儲存該使用者所擁有的許可權名稱及許可權最高等級
			HashMap<String,Integer> perms=new HashMap<>();
			//將所擁有的角色型別中所擁有的許可權轉儲存至使用者的perms中
			int rolesNum=sc.nextInt();
			for(int t=0;t<rolesNum;t++)//彙總所擁有的全部角色許可權
			{
				//由角色名得到該角色所有許可權名及等級
				for(Map.Entry<String, Integer> m:roles.get(sc.next()).entrySet())
				{
					String key=m.getKey();
					int value=m.getValue();
					if(perms.containsKey(key))//若存在該許可權則取該許可權的最高等級進行儲存
					{
						if(perms.get(key)<value)//比較許可權等級大小
							perms.put(key, value);
					}
					else
						perms.put(key, value);
				}
			}
			users.put(userName, perms);
		}
		
		int q=sc.nextInt();//查詢語句數目
		String[] result=new String[q];
		Query:for(int i=0;i<q;i++)//執行查詢
		{
			String squeryName=sc.next();//待查詢使用者名稱
			String[] temp=sc.next().split(":");//下標0為待查詢許可權名,若存在下標1則為許可權等級
			if(!users.containsKey(squeryName))//判斷使用者是否存在
			{
				result[i]="false";
				continue Query;
			}
			else if(!perm.containsKey(temp[0]))//判斷許可權是否存在
			{
				result[i]="false";
				continue Query;
			}
			else if(temp.length==1)//查詢許可權不分等級
			{
				result[i]=queryResult(squeryName,temp[0],-1);
			}
			else {//查詢許可權分等級
				result[i]=queryResult(squeryName,temp[0],Integer.valueOf(temp[1]));
			}
		}
		for(String s:result)
			System.out.println(s);
	}
	//執行許可權查詢並返回結果,引數待查詢使用者名稱,待查詢許可權名,所需查詢該許可權的等級
	public static String queryResult(String userName,String permName,int queryLevel)
	{
		if(!users.get(userName).containsKey(permName))//判斷該使用者是否具有該許可權
		{
			return "false";
		}
		else//判斷該使用者該許可權等級是否匹配
		{
			if(queryLevel!=-1)//查詢分等級
			{
				//判斷使用者所擁有許可權是否大於所需查詢許可權
				if(users.get(userName).get(permName)>=queryLevel)
					return "true";
				else
					return "false";
			}
			else//查詢不分等級
			{
				if(perm.get(permName)==-1)//許可權本身不分級,返回True/False
					return "true";
				else//許可權本身分級,返回最高級別
					return String.valueOf(users.get(userName).get(permName));
			}
			
		}
	}

}