1. 程式人生 > 其它 >【Lintcode】284. Matching Subsequences

【Lintcode】284. Matching Subsequences

技術標籤:# 棧、佇列、串及其他資料結構leetcode字串演算法java資料結構

題目地址:

https://www.lintcode.com/problem/matching-subsequences/description

給定一個長 n n n的字串 s s s,再給定若干詢問,每次詢問一個字串 w w w是否是 s s s的子序列。

思路是序列自動機。可以模仿https://blog.csdn.net/qq_46105170/article/details/111661192來做。程式碼如下:

import java.util.ArrayList;
import java.util.Arrays;
import
java.util.List; public class Solution { /** * @param source: A string * @param words: A list of string * @return: return list of words[i] that is a subsequence of source. */ public List<String> MatchingSubsequences(String source, List<String> words) { // write your code here
List<String> res = new ArrayList<>(); // auto[i][k]表示的是source[i - 1]之後字元k首次出現的位置是第幾(從1開始計數) int[][] auto = new int[source.length() + 1][128]; // -1是不合法狀態,先將每個entry都初始化為-1 for (int[] row : auto) { Arrays.fill(row, -1); } // 求解auto可以用動態規劃來做
for (int i = source.length() - 1; i >= 0; i--) { for (int j = 0; j < 128; j++) { auto[i][j] = auto[i + 1][j]; } auto[i][source.charAt(i)] = i + 1; } for (String word : words) { int idx = 0; for (int i = 0; i < word.length() && idx != -1; i++) { idx = auto[idx][word.charAt(i)]; } if (idx != -1) { res.add(word); } } return res; } }

預處理時間複雜度 O ( n ) O(n) O(n),每次詢問時間 O ( l w ) O(l_w) O(lw),空間 O ( n ) O(n) O(n)

暴力法當然也是可以做的。程式碼如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    /**
     * @param source: A string
     * @param words:  A list of string
     * @return: return list of words[i] that is a subsequence of source.
     */
    public List<String> MatchingSubsequences(String source, List<String> words) {
        // write your code here
        // idx[i]代表words[i]這個查詢串已經匹配到什麼下標了
        int[] idx = new int[words.size()];
        for (int i = 0; i < source.length(); i++) {
            for (int j = 0; j < words.size(); j++) {
                // 若已經匹配則跳過
                if (idx[j] == -1) {
                    continue;
                } 

				// 如果查詢串words[j]能和當前的source[i]匹配,則後移匹配位置
				if (words.get(j).charAt(idx[j]) == source.charAt(i)) {
                    idx[j]++;
                }
                
                // 如果查詢串words[j]匹配成功了,標記為-1
                if (idx[j] == words.get(j).length()) {
                    idx[j] = -1;
                }
            }
        }
        
        // 遍歷一遍idx陣列,將匹配成功的加入答案
        List<String> res = new ArrayList<>();
        for (int i = 0; i < words.size(); i++) {
            if (idx[i] == -1) {
                res.add(words.get(i));
            }
        }
        
        return res;
    }
}

時間複雜度 O ( n k ) O(nk) O(nk) k k k為詢問次數。由於一般而言詢問字串長度是遠小於 n n n的,所以暴力法的複雜度是比自動機更高的。