1
+ class Solution {
2
+ String str ;
3
+ Node [] nodes ;
4
+ int [] starNodeIndexes ;
5
+ int cursor ;
6
+ int nodeCursor ;
7
+
8
+ class Node {
9
+ protected char pattern ;
10
+ protected int matchIndex ;
11
+
12
+ public Node (char pattern ) {
13
+ this .pattern = pattern ;
14
+ }
15
+
16
+ public boolean isMatch () {
17
+ return str .charAt (matchIndex ) == pattern ;
18
+ }
19
+ public boolean isMatch (char c ) {
20
+ return c == pattern ;
21
+ }
22
+ }
23
+
24
+ class DotNode extends Node {
25
+ public DotNode (char pattern ) {
26
+ super (pattern );
27
+ }
28
+ @ Override
29
+ public boolean isMatch () {
30
+ return true ;
31
+ }
32
+ @ Override
33
+ public boolean isMatch (char c ) {
34
+ return true ;
35
+ }
36
+ }
37
+
38
+ class StarNode extends Node {
39
+ protected int matchLength ;
40
+ protected Node patternNode ;
41
+ public StarNode (char pattern ) {
42
+ super (pattern );
43
+ }
44
+ @ Override
45
+ public boolean isMatch () {
46
+ int max = matchIndex + matchLength ;
47
+ for (int i = matchIndex ; i < max ; i ++) {
48
+ if (!patternNode .isMatch (str .charAt (matchIndex ))) {
49
+ return false ;
50
+ }
51
+ }
52
+ return true ;
53
+ }
54
+ public int maxMatchLength (int allowMax ) {
55
+ int i = 0 ;
56
+ for (; i < allowMax ; i ++) {
57
+ if (!patternNode .isMatch (str .charAt (matchIndex + i ))) {
58
+ break ;
59
+ }
60
+ }
61
+ return i ;
62
+ }
63
+ }
64
+
65
+ private void compile (String p ) {
66
+ List <Node > list = new ArrayList <>();
67
+ int starCount = 0 ;
68
+ for (int i = 0 ; i < p .length (); i ++) {
69
+ char reg = p .charAt (i );
70
+ Node node ;
71
+ if (p .charAt (i ) == '.' ) {
72
+ node = new DotNode (reg );
73
+ } else {
74
+ node = new Node (reg );
75
+ }
76
+ if (i < p .length () - 1 && p .charAt (i + 1 ) == '*' ) {
77
+ StarNode snode = new StarNode ('*' );
78
+ snode .patternNode = node ;
79
+ list .add (snode );
80
+ i ++;
81
+ starCount ++;
82
+ } else {
83
+ list .add (node );
84
+ }
85
+ }
86
+ nodes = list .toArray (new Node [list .size ()]);
87
+ starNodeIndexes = new int [starCount ];
88
+ starCount = 0 ;
89
+ for (int i = 0 ; i < nodes .length ; i ++) {
90
+ if (nodes [i ] instanceof StarNode ) {
91
+ starNodeIndexes [starCount ++] = i ;
92
+ }
93
+ }
94
+ }
95
+
96
+ public boolean isMatch (String s , String p ) {
97
+ if (s .length () == 0 && p .length () == 0 ) {
98
+ return true ;
99
+ }
100
+ if (s .length () > 0 && p .length () == 0 ) {
101
+ return false ;
102
+ }
103
+ str = s ;
104
+
105
+ compile (p );
106
+
107
+ if (s .length () < nodes .length - starNodeIndexes .length
108
+ || (starNodeIndexes .length == 0 && s .length () != nodes .length )) {
109
+ return false ;
110
+ }
111
+
112
+ nodeCursor = 0 ;
113
+ cursor = 0 ;
114
+ int starCount = 0 ;
115
+ while (nodeCursor < nodes .length ) {
116
+ Node node = nodes [nodeCursor ];
117
+ if (node instanceof StarNode ) {
118
+ StarNode snode = (StarNode )node ;
119
+ snode .matchIndex = cursor ;
120
+
121
+ int restCharLength = s .length () - cursor ;
122
+ int minLength = starNodeIndexes .length - starCount > 1 ? 0 : restCharLength - (nodes .length - nodeCursor - 1 );
123
+ int maxLength = restCharLength - (nodes .length - nodeCursor ) + starNodeIndexes .length - starCount ;
124
+
125
+ int length = snode .maxMatchLength (maxLength );
126
+
127
+ if (length >= minLength ) {
128
+ snode .matchLength = length ;
129
+ starCount ++;
130
+ nodeCursor ++;
131
+ cursor += length ;
132
+ continue ;
133
+ } else { // 进入后面的回退到上一个*的算法
134
+ snode .matchLength = 0 ;
135
+ }
136
+
137
+ } else {
138
+ node .matchIndex = cursor ;
139
+ if (node .isMatch ()) {
140
+ cursor ++;
141
+ nodeCursor ++;
142
+ continue ;
143
+ }
144
+ }
145
+ if (starCount > 0 ) {
146
+ // 回退到'*'匹配的位置,并且把*匹配的个数减一
147
+ while (starCount > 0 ) {
148
+ int iStarCount = starCount - 1 ;
149
+ int iNodeCursor = starNodeIndexes [iStarCount ];
150
+ StarNode snode = (StarNode ) nodes [iNodeCursor ];
151
+ int iCursor = snode .matchIndex ;
152
+
153
+ int iRestCharLength = s .length () - iCursor + 1 ;
154
+ int minLength = starNodeIndexes .length - iStarCount > 1 ? 0 : iRestCharLength - (nodes .length - iNodeCursor - 1 );
155
+
156
+ if (snode .matchLength > minLength ) {
157
+ snode .matchLength = snode .matchLength - 1 ;
158
+ nodeCursor = iNodeCursor + 1 ;
159
+ cursor = iCursor + snode .matchLength ;
160
+ break ;
161
+ } else {
162
+ starCount --;
163
+ }
164
+ }
165
+ if (starCount > 0 ) {
166
+ continue ;
167
+ }
168
+ }
169
+ return false ;
170
+ }
171
+ return true ;
172
+ }
173
+ }
0 commit comments