题目地址:
https://www.lintcode.com/problem/1581/
给定一个长 n n n的字符串 s s s,和一个字符串的集合 S S S,问集合里最长的是 s s s的子序列的字符串是哪个,如果有多个,返回字典序最小的。
逐个查看集合里每个字符串是否是 s s s的子序列,可以用序列自动机加速此过程,参考https://blog.csdn.net/qq_46105170/article/details/119269166。代码如下:
import java.util.Set;
public class Solution {
/**
* @param word_dict: a dictionary
* @param s: a string
* @return: the longest one existed in the given dictionary
*/
public String longestSubsequence(Set<String> word_dict, String s) {
// Write your code here
int[][] dfa = buildDfa(s);
String res = "";
for (String str : word_dict) {
// 如果是子序列,并且或者更长,或者一样长但字典序更小,则更新答案
if (check(str, dfa) && (str.length() > res.length() || (str.length() == res.length() && str.compareTo(res) < 0))) {
res = str;
}
}
return res;
}
private boolean check(String s, int[][] dfa) {
if (s.length() >= dfa.length) {
return false;
}
for (int i = 0, pos = 0; i < s.length(); i++) {
pos = dfa[pos][s.charAt(i) - 'a'];
if (pos == 0) {
return false;
}
}
return true;
}
private int[][] buildDfa(String s) {
int[][] dfa = new int[s.length() + 1][26];
for (int i = s.length() - 1; i >= 0; i--) {
for (int j = 0; j < 26; j++) {
dfa[i][j] = dfa[i + 1][j];
}
dfa[i][s.charAt(i) - 'a'] = i + 1;
}
return dfa;
}
}
时间复杂度 O ( n l + l s ) O(nl+l_s) O(nl+ls), n n n是 S S S里字符串的个数, l l l是 S S S里最长字符串的长度。