題目描述
在如XML或是HTML的標籤語言中,內容被包含在起始的標籤和結束的標籤,像是:
<tag>contents</tag>
結束的標籤必須要和起始的標籤名稱相同,而且開頭必須是「/」。
給定一個標籤語言的文字字串,解析這個文字,將包含在多個標籤裡面的內容抽取出來,但文字需符合以下規則。
起始標籤和結束標籤的名稱必須一致,舉例:
<h1>Hello World</h2>
以上這段HTML程式碼是不正確的,因為它的起始標籤是「h1」,結束標籤卻是用「h2」。
標籤可以是巢狀的,但如果內容是在巢狀標籤之間,則是不正確的,舉例:
<h1><a>contents</a>invalid</h1>
以上這段HTML程式碼的內容「contents」是正確的,但是內容「invalid」是不正確的。
標籤可以包含所有可以印出的字元。
原題網址
輸入格式
第一行輸入為一個整數N,範圍是1到100(包含1和100),為測試資料的數量。
接下來的N行,每行均為一組測試資料,要輸入標籤語言文字。每行的最大長度為104個字元,整個文字總共的字元數量不會超過106個。字元均為可以被印出的字元。
輸出格式
針對每行測試資料,輸出他們的標籤包含的正確內容。如果有多個內容,換行分隔。
範例輸入
<h1>Nayeem loves counseling</h1>
<h1><h1>Sanjay has no watch</h1></h1><par>So wait for a while</par>
<Amee>safat codes like a ninja</amee>
<SA premium>Imtiaz has a secret crush</SA premium>
範例輸出
Sanjay has no watch
So wait for a while
None
Imtiaz has a secret crush
解題概念
使用Pattern和Matcher物件,來找出每個符合格式的標籤區段。
由於起始標籤和結束標籤必須要是相同的標籤名稱,因此先可以寫出如下的Pattern:
"<()></\\1>"
「\1」所指的是第一個group所包含的段落。group就是括號內的內容,一組括號從左至右出現的順序,就是它們的號碼,從1開始。
由於標籤語言的文字都是可以顯示出來的字元,在Java程式語言的正規表示式中,可以使用「\p{Print}」來代表所有可以印出的字元。但是標籤語言已經有使用到「<」和「>」作為識別標籤的字元,因此如果不是要作為識別標籤用途的話,其餘的字元應避免使用「<」和「>」。所以其餘的字元的Pattern可以這樣來表示:
"[\\p{Print}&&[^<>]]"
合併後,我們可以得到最後Pattern的正規表示式:
"<([\\p{Print}&&[^<>]]+)>([\\p{Print}&&[^<>]]+)</\\1>"
使用Pattern的compile方法可以將字串轉成Pattern物件。接著使用Pattern物件的matcher方法並代入要進行處理的文字字串,即可產生出Matcher物件。使用Matcher物件的find方法可以尋找下一個符合Pattern的文字段落。使用Matcher物件的group方法可以取得符合Pattern中指定位置之group的內容,在上面寫出來的正規表示式中,標籤內容的group位置為2。
參考答案
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Solution {
public static void main(final String[] args) {
final Scanner in = new Scanner(System.in);
int testCases = Integer.parseInt(in.nextLine());
final Pattern pattern = Pattern.compile("<([\\p{Print}&&[^<>]]+)>([\\p{Print}&&[^<>]]+)</\\1>");
while (testCases > 0) {
final String line = in.nextLine();
final Matcher m = pattern.matcher(line);
if (m.find()) {
System.out.println(m.group(2));
while (m.find()) {
System.out.println(m.group(2));
}
} else {
System.out.println("None");
}
testCases--;
}
}
}