最近临近毕业,准备走人,闲来刷下题。挺有意思的字符串题目,先Trie后DFS。将模式串组成Trie,然后上面跑DFS。
易错的地方几个(惭愧地参考了别人的心得才发现),模式串有可能有一模一样的,所以DFS时必须都找出来。
import java.util.*; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); Trie trie = new Trie(); int m,n; m = scan.nextInt(); n = scan.nextInt(); for(int i=0;i<m;i++) { String tmpStr = scan.next(); trie.Insert(tmpStr, i); } for(int i=0;i<n;i++) { String tmpStr= scan.next(); Node cNode = trie.root; ArrayList<Integer> ids = new ArrayList<Integer>(); trie.DFSSearch(cNode, tmpStr, 0, ids); if(ids.size() == 0) { System.out.println("Not match"); } else { Collections.sort(ids); int prev = -1; for(int j=0;j<ids.size();j++) { if(ids.get(j) == prev) { continue; } System.out.print(ids.get(j) + " "); prev = ids.get(j); } System.out.print('\n'); } } } } class Node{ ArrayList<Integer> sIds; Node[] children; public Node() { sIds = new ArrayList<Integer>(); children = new Node[28]; } } class Trie { public Node root; public Trie() { root = new Node(); } public void Insert(String str, int iStrId) { int iStrPos = 0; Node cNode = root; while(iStrPos < str.length()) { int iCPos; if(str.charAt(iStrPos) == '*') iCPos = 26; else if(str.charAt(iStrPos) == '?') iCPos = 27; else iCPos = str.charAt(iStrPos) - 'a'; if(cNode.children[iCPos] == null) { cNode.children[iCPos] = new Node(); } cNode = cNode.children[iCPos]; iStrPos++; } cNode.sIds.add(iStrId); } public void DFSSearch(Node cNode, String str, int iStrPos, ArrayList<Integer> answerIds) { if(iStrPos == str.length()) {//Finish Matching, output the answer. SearchAnswer(cNode, answerIds); return; } else {//Go on matching. if (cNode.children[str.charAt(iStrPos) - 'a'] != null) { // Match DFSSearch(cNode.children[str.charAt(iStrPos) - 'a'], str, iStrPos + 1, answerIds); } if (cNode.children[27] != null) { // Match DFSSearch(cNode.children[27], str, iStrPos + 1, answerIds); } if (cNode.children[26] != null) { /*下面两行注释掉的代码是个易错点,特别第二行,因为如果对于每一个树节点,如果不往下走,无法知道上一个对应的字符串序号。 * 这样子讲很抽象,举个例子。比如有两个pattern * 1:* * 2:? * 给定字符串w。跑出来结果你就知道啥问题了。**/ // Ignore //DFSSearch(cNode.children[26], str, iStrPos, answerIds); // Match //DFSSearch(cNode, str, iStrPos + 1, answerIds); for(int i=iStrPos; i<=str.length();i++) { DFSSearch(cNode.children[26],str,i,answerIds); } } } } public void SearchAnswer(Node cNode, ArrayList<Integer> ids) { for(int i=0;i<cNode.sIds.size();i++) { ids.add(cNode.sIds.get(i)); } if(cNode.children[26] != null) { SearchAnswer(cNode.children[26], ids); } } }