1. 程式人生 > >字串匹配演算法之Sunday演算法

字串匹配演算法之Sunday演算法

  1 import java.util.HashMap;
  2 import java.util.LinkedList;
  3 import java.util.List;
  4 import java.util.Map;
  5 
  6 /** 
  7  * @author Scott
  8  * @date 2013年12月28日 
  9  * @description
 10  */
 11 public class SundySearch {
 12     String text = null;
 13     String pattern = null;
 14     int
currentPos = 0; 15 16 /** 17 * 匹配後的子串第一個字元位置列表 18 */ 19 List<Integer> matchedPosList = new LinkedList<Integer>(); 20 21 /** 22 * 匹配字元的Map,記錄改匹配字串有哪些char並且每個char最後出現的位移 23 */ 24 Map<Character, Integer> map = new HashMap<Character, Integer>();
25 26 public SundySearch(String text, String pattern) { 27 this.text = text; 28 this.pattern = pattern; 29 this.initMap(); 30 }; 31 32 /** 33 * Sunday匹配時,用來儲存Pattern中每個字元最後一次出現的位置,從左到右的順序 34 */ 35 private void initMap() { 36 for (int
i = 0; i < pattern.length(); i++) { 37 this.map.put(pattern.charAt(i), i); 38 39 } 40 } 41 42 /** 43 * 普通的字串遞迴匹配,匹配失敗就前進一位 44 */ 45 public List<Integer> normalMatch() { 46 //匹配失敗,繼續往下走 47 if (!matchFromSpecialPos(currentPos)) { 48 currentPos += 1; 49 50 if ((text.length() - currentPos) < pattern.length()) { 51 return matchedPosList; 52 } 53 normalMatch(); 54 } else { 55 //匹配成功,記錄位置 56 matchedPosList.add(currentPos); 57 currentPos += 1; 58 normalMatch(); 59 } 60 61 return matchedPosList; 62 } 63 64 /** 65 * Sunday匹配,假定Text中的K字元的位置為:當前偏移量+Pattern字串長度+1 66 */ 67 public List<Integer> sundayMatch() { 68 // 如果沒有匹配成功 69 if (!matchFromSpecialPos(currentPos)) { 70 // 如果Text中K字元沒有在Pattern字串中出現,則跳過整個Pattern字串長度 71 if ((currentPos + pattern.length() + 1) < text.length() 72 && !map.containsKey(text.charAt(currentPos + pattern.length() + 1))) { 73 currentPos += pattern.length(); 74 }else { 75 // 如果Text中K字元在Pattern字串中出現,則將Text中K字元的位置和Pattern字串中的最後一次出現K字元的位置對齊 76 if ((currentPos + pattern.length() + 1) > text.length()) { 77 currentPos += 1; 78 } else { 79 currentPos += pattern.length() - (Integer) map.get(text.charAt(currentPos + pattern.length())); 80 } 81 } 82 83 // 匹配完成,返回全部匹配成功的初始位移 84 if ((text.length() - currentPos) < pattern.length()) { 85 return matchedPosList; 86 } 87 88 sundayMatch(); 89 }else { 90 // 匹配成功前進一位然後再次匹配 91 matchedPosList.add(currentPos); 92 currentPos += 1; 93 sundayMatch(); 94 } 95 return matchedPosList; 96 } 97 98 /** 99 * 檢查從Text的指定偏移量開始的子串是否和Pattern匹配 100 */ 101 public boolean matchFromSpecialPos(int pos) { 102 if ((text.length()-pos) < pattern.length()) { 103 return false; 104 } 105 106 for (int i = 0; i < pattern.length(); i++) { 107 if (text.charAt(pos + i) == pattern.charAt(i)) { 108 if (i == (pattern.length()-1)) { 109 return true; 110 } 111 continue; 112 } else { 113 break; 114 } 115 } 116 117 return false; 118 } 119 120 public static void main(String[] args) { 121 SundySearch sundySearch = new SundySearch("hello 啊啊 阿道夫 adfsadfklf adf234masdfsdfdsfdsfdsffwerwrewrerwerwersdf2666sdflsdfk", "adf"); 122 123 long begin = System.nanoTime(); 124 System.out.println("NormalMatch:" + sundySearch.normalMatch()); 125 System.out.println("NormalMatch:" + (System.nanoTime() - begin)); 126 127 begin = System.nanoTime(); 128 System.out.println("SundayMatch:" + sundySearch.sundayMatch()); 129 System.out.println("SundayMatch:" + (System.nanoTime() - begin)); 130 131 } 132 }