原题网址:https://leetcode.com/problems/word-pattern-ii/
Given a pattern
and a string str
, find if str
follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern
and a non-empty substring in str
.
Examples:
- pattern =
"abab"
, str ="redblueredblue"
should return true. - pattern =
"aaaa"
, str ="asdasdasdasd"
should return true. - pattern =
"aabb"
, str ="xyzabcxzyabc"
should return false.
Notes:
You may assume both pattern
and str
contains only lowercase letters.
方法:深度优先搜索。
public class Solution {
private int pcount = 0;
private int[] acount = new int[26];
private int[] ntoa = new int[26];
private int[] aton = new int[26];
private char[] sa;
private String str;
private boolean matched;
private char[] pa;
private void find(int[] lens, int len, int step) {
if (matched) return;
if (len>sa.length) return;
else if (len==sa.length) {
if (step!=lens.length) return;
// len==sa.length && step==lens.length
int pos = 0;
String[] map = new String[26];
for(int i=0; i<pa.length; i++) {
String s = str.substring(pos, pos+lens[aton[pa[i]-'a']]);
if (map[aton[pa[i]-'a']] == null) map[aton[pa[i]-'a']] = s;
else if (!map[aton[pa[i]-'a']].equals(s)) return;
pos += lens[aton[pa[i]-'a']];
}
for(int i=0; i<pa.length-1; i++) {
for(int j=i+1; j<pa.length; j++) {
if (pa[i] != pa[j] && map[aton[pa[i]-'a']].equals(map[aton[pa[j]-'a']])) return;
}
}
matched = true;
return;
} else if (step==lens.length) return;
for(int i=1; len + acount[this.ntoa[step]]*i <= sa.length; i ++) {
lens[step] = i;
find(lens, len + acount[this.ntoa[step]]*i, step + 1);
}
}
public boolean wordPatternMatch(String pattern, String str) {
this.str = str;
this.sa = str.toCharArray();
this.pa = pattern.toCharArray();
for(int i=0; i<this.pa.length; i++) {
int j=this.pa[i]-'a';
if (this.acount[j] == 0) {
this.aton[j] = this.pcount;
this.ntoa[this.pcount++] = j;
}
this.acount[j] ++;
}
find(new int[this.pcount], 0, 0);
return matched;
}
}
优化:
public class Solution {
String str;
char[] pa;
int pcount;
int[] aton = new int[26];
int[] ntoa = new int[26];
int[] acount = new int[26];
private boolean match(int[] lens, int len, int step) {
if (step == lens.length) {
if (len != str.length()) return false;
String[] map = new String[26];
int pos = 0;
for(int i=0; i<pa.length; i++) {
String s = str.substring(pos, pos+lens[aton[pa[i]-'a']]);
if (map[aton[pa[i]-'a']] == null) map[aton[pa[i]-'a']] = s;
else if (!s.equals(map[aton[pa[i]-'a']])) return false;
pos += lens[aton[pa[i]-'a']];
}
for(int i=0; i<pcount-1; i++) {
for(int j=i+1; j<pcount; j++) {
if (map[i].equals(map[j])) return false;
}
}
return true;
}
for(int i=1; len+acount[ntoa[step]]*i+(lens.length-1-step)<=str.length(); i++) {
lens[step] = i;
if (match(lens, len+acount[ntoa[step]]*i, step+1)) return true;
}
return false;
}
public boolean wordPatternMatch(String pattern, String str) {
pa = pattern.toCharArray();
for(int i=0; i<pa.length; i++) {
int j=pa[i]-'a';
if (acount[j]==0) {
aton[j]=pcount;
ntoa[pcount]=j;
pcount++;
}
acount[j]++;
}
this.str = str;
return match(new int[pcount], 0, 0);
}
}
优化:
public class Solution {
private boolean find(char[] pattern, int step, int len, String str, String[] map, Map<String, Character> inverse) {
if (step == pattern.length) {
if (len == str.length()) return true;
return false;
}
if (map[pattern[step] - 'a'] != null) {
if (len + map[pattern[step] - 'a'].length() > str.length()) return false;
if (!map[pattern[step] - 'a'].equals(str.substring(len, len + map[pattern[step] - 'a'].length()))) return false;
return find(pattern, step + 1, len + map[pattern[step] - 'a'].length(), str, map, inverse);
}
int from = 1, to = (str.length() - len) - (pattern.length - 1 - step);
if (from > to) return false;
if (step == pattern.length - 1) from = to;
for(int i = from; i <= to; i++) {
String sub = str.substring(len, len + i);
Character ch = inverse.get(sub);
if (ch != null) continue;
inverse.put(sub, pattern[step]);
map[pattern[step] - 'a'] = sub;
if (find(pattern, step + 1, len + i, str, map, inverse)) return true;
inverse.remove(sub);
map[pattern[step] - 'a'] = null;
}
return false;
}
public boolean wordPatternMatch(String pattern, String str) {
return find(pattern.toCharArray(), 0, 0, str, new String[26], new HashMap<>());
}
}