解题思路

这是一个字符串匹配和动态规划问题。使用 算法找到所有模式串的匹配位置,然后用动态规划求解最大不相交子串数量。

关键点:

  1. 使用 算法高效查找所有匹配位置
  2. 用动态规划数组 表示到位置 的最大不相交子串数量
  3. 对每个位置,考虑是否选择以该位置结尾的匹配

算法步骤:

  1. 对每个模式串进行 匹配
  2. 记录每个位置结尾的所有可能匹配
  3. 动态规划求解最优结果

代码

#include <bits/stdc++.h>
using namespace std;

class StringMatcher {
private:
    static const int MAXN = 100005;
    vector<int> next;
    vector<vector<int>> matches;
    vector<int> dp;
    
public:
    StringMatcher(int size) {
        next.resize(MAXN);
        matches.resize(MAXN);
        dp.resize(MAXN);
    }
    
    void buildNext(const string& pattern) {
        int len = pattern.length();
        next[0] = -1;
        int i = 0, j = -1;
        
        while (i < len) {
            if (j == -1 || pattern[i] == pattern[j]) {
                i++; j++;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
    }
    
    void kmpMatch(const string& text, const string& pattern) {
        buildNext(pattern);
        int n = text.length(), m = pattern.length();
        int i = 0, j = 0;
        
        while (i < n) {
            if (j == -1 || text[i] == pattern[j]) {
                i++; j++;
            } else {
                j = next[j];
            }
            
            if (j == m) {
                matches[i-1].push_back(i-m-1);
                j = next[j];
            }
        }
    }
    
    int solve(const string& text, const vector<string>& patterns) {
        int textLen = text.length();
        
        // 对每个模式串进行KMP匹配
        for (const string& pattern : patterns) {
            kmpMatch(text, pattern);
        }
        
        // 动态规划求解
        for (int i = 0; i < textLen; i++) {
            dp[i+1] = dp[i];
            for (int start : matches[i]) {
                dp[i+1] = max(dp[i+1], dp[start+1] + 1);
            }
        }
        
        return dp[textLen];
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    
    vector<string> patterns(n);
    for (int i = 0; i < n; i++) {
        cin >> patterns[i];
    }
    
    string text;
    cin >> text;
    
    StringMatcher matcher(text.length());
    cout << matcher.solve(text, patterns) << endl;
    
    return 0;
}
import java.util.*;

public class Main {
    static class StringMatcher {
        private static final int MAXN = 100005;
        private int[] next;
        private List<List<Integer>> matches;
        private int[] dp;
        
        public StringMatcher(int size) {
            next = new int[MAXN];
            matches = new ArrayList<>(MAXN);
            dp = new int[MAXN];
            
            for (int i = 0; i < MAXN; i++) {
                matches.add(new ArrayList<>());
            }
        }
        
        private void buildNext(String pattern) {
            int len = pattern.length();
            next[0] = -1;
            int i = 0, j = -1;
            
            while (i < len) {
                if (j == -1 || pattern.charAt(i) == pattern.charAt(j)) {
                    i++; j++;
                    next[i] = j;
                } else {
                    j = next[j];
                }
            }
        }
        
        private void kmpMatch(String text, String pattern) {
            buildNext(pattern);
            int n = text.length(), m = pattern.length();
            int i = 0, j = 0;
            
            while (i < n) {
                if (j == -1 || text.charAt(i) == pattern.charAt(j)) {
                    i++; j++;
                } else {
                    j = next[j];
                }
                
                if (j == m) {
                    matches.get(i-1).add(i-m-1);
                    j = next[j];
                }
            }
        }
        
        public int solve(String text, List<String> patterns) {
            int textLen = text.length();
            
            for (String pattern : patterns) {
                kmpMatch(text, pattern);
            }
            
            for (int i = 0; i < textLen; i++) {
                dp[i+1] = dp[i];
                for (int start : matches.get(i)) {
                    dp[i+1] = Math.max(dp[i+1], dp[start+1] + 1);
                }
            }
            
            return dp[textLen];
        }
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        List<String> patterns = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            patterns.add(sc.next());
        }
        
        String text = sc.next();
        
        StringMatcher matcher = new StringMatcher(text.length());
        System.out.println(matcher.solve(text, patterns));
        
        sc.close();
    }
}
class StringMatcher:
    def __init__(self, size):
        self.MAXN = 100005
        self.next = [-1] * self.MAXN
        self.matches = [[] for _ in range(self.MAXN)]
        self.dp = [0] * self.MAXN
        
    def build_next(self, pattern):
        length = len(pattern)
        self.next[0] = -1
        i, j = 0, -1
        
        while i < length:
            if j == -1 or pattern[i] == pattern[j]:
                i += 1
                j += 1
                self.next[i] = j
            else:
                j = self.next[j]
                
    def kmp_match(self, text, pattern):
        self.build_next(pattern)
        n, m = len(text), len(pattern)
        i = j = 0
        
        while i < n:
            if j == -1 or text[i] == pattern[j]:
                i += 1
                j += 1
            else:
                j = self.next[j]
                
            if j == m:
                self.matches[i-1].append(i-m-1)
                j = self.next[j]
                
    def solve(self, text, patterns):
        text_len = len(text)
        
        for pattern in patterns:
            self.kmp_match(text, pattern)
            
        for i in range(text_len):
            self.dp[i+1] = self.dp[i]
            for start in self.matches[i]:
                self.dp[i+1] = max(self.dp[i+1], self.dp[start+1] + 1)
                
        return self.dp[text_len]

# 主函数
if __name__ == "__main__":
    n = int(input())
    patterns = [input() for _ in range(n)]
    text = input()
    
    matcher = StringMatcher(len(text))
    print(matcher.solve(text, patterns))

算法及复杂度

  • 算法: + 动态规划
  • 时间复杂度:,其中 是文本长度, 是所有模式串长度之和
  • 空间复杂度:,用于存储 数组和匹配位置