学习了 KMP(Knuth-Morris-Pratt) 字符串匹配算法,记录下代码。
public class KMP {
private int[][] dp;
private String pat;
public KMP(String pat) {
this.pat = pat;
int M = pat.length();
// dp[状态][字符] = 下个状态
dp = new int[M][256];
// base case
dp[0][pat.charAt(0)] = 1;
// 影子状态 X 初始为 0
int X = 0;
// 构建状态转移图(稍改的更紧凑了)
for (int j = 1; j < M; j++) {
for (int c = 0; c < 256; c++) {
dp[j][c] = dp[X][c];
dp[j][pat.charAt(j)] = j + 1;
// 更新影子状态
X = dp[X][pat.charAt(j)];
}
}
public int search(String txt) {
int M = pat.length();
int N = txt.length();
// pat 的初始态为 0
int j = 0;
for (int i = 0; i < N; i++) {
// 计算 pat 的下一个状态
j = dp[j][txt.charAt(i)];
// 到达终止态,返回结果
if (j == M) return i - M + 1;
}
// 没到达终止态,匹配失败
return -1;
}
}
运用KMP:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10010;
int dp[maxn][256];
string pat;
string txt;
void kmp()
{
int M = pat.length();
dp[0][pat[0]] = 1;
int X = 0;
for(int j = 1; j < M; ++j)
{
for(int c = 0; c < 256; ++c)
{
if (pat[j] == c) dp[j][c] = j + 1;
else dp[j][c] = dp[X][c];
}
X = dp[X][pat[j]];
}
}
int search()
{
int M = pat.length();
int N = txt.length();
int j = 0;
for(int i = 0; i < N; ++i)
{
j = dp[j][txt[i]];
if(j == M) return i - M + 1;
}
return -1;
}
int main()
{
cin >> pat;
kmp();
cin >> txt;
while(txt != "")
{
int pos = search();
if(pos == -1) cout << "不匹配\n";
else cout << "首次匹配位置在" << pos << endl;
cin >> txt;
}
}
可以参考一下https://mp.weixin.qq.com/s/kCjRuY6ygYJWWX5HPVLa5A讲的真好。