思路:
首先计算出模板字符串每个位置的最长公共前后缀,通过最长公共前后缀可以在和原始字符串进行比较的时候只需要O(n)的时间比较完成。
而【计算模板字符串每个位置的最长公共前后缀】,【计算原始字符串和模板字符串的最长匹配公共前缀】是一样的做法。前者,模板字符串的前缀和当前后缀进行比较,记录每个位置匹配的最长前后缀,当前位置前缀串和后缀串相等的时候,其最长匹配前缀就是之前已经记录的最长匹配前缀加1,否则最长匹配长度缩小到前一个匹配的最长前缀,知道匹配的最长前缀为0。后者,不一样的是拿模板字符串作为前缀进行比较,其他和第一个问题一样。
具体可查看《算法导论》,b站的一些教学视频。
实现:
代码实现示例:
#include <iostream>using namespace std;int m, n;char str[] = "@bacbababaabcbab";char pattern[] = "@ababaca";int pi[10];int f[100000];void compute_next(){int j = 0;pi[1] = 0;for(int i = 2; i <= m; i++){while(j > 0 && pattern[i] != pattern[j+1]) j = pi[j];if(pattern[i] == pattern[j+1])j++;pi[i] = j;}}void compute_f(){int j = 0;for(int i = 1; i <= n; i++){while(j > 0 && str[i] != pattern[j + 1])j = pi[j];if(str[i] == pattern[j + 1])j++;f[i] = j;}}int main(){n = 15, m = 7;compute_next();compute_f();for(int i = 1; i <= n; i++){cout<<"i = "<<i<<", "<<f[i]<<endl;}return 0;}
