文字列マッチング(マシンでの再テストのために送信)

序文:

21.再テストに参加できるかどうかに関係なく、道路に書かれたゴミコードを記録します。もともと「AlgorithmNotes」をかじったのですが、やりすぎたので、Kingway ComputerTestGuideに変更しました。

タイトル説明:

テキスト内のパターンのすべての出現を見つけることは、テキスト編集プログラムで頻繁に発生する問題です。通常、テキストは編集中のドキュメントであり、検索されるパターンはユーザーが指定した特定の単語です。テキストは長さnの配列T [1…n]であり、パターンは長さm <= nの配列P [1…m]であると想定します。さらに、PとTの要素はすべてアルファベットであると想定します。 (∑ = {a、b…、z})。文字配列PおよびTは、文字列と呼ばれることがよくあります。パターンPは、0 <= s <= nかつT [s + 1…s + m] = P [1…m]の場合(つまり、T [s + j] =の場合)、テキストTのシフトsで発生すると言います。 P [j]、1 <= j <= mの場合)。TのシフトsでPが発生する場合は、有効なシフトと呼びます。それ以外の場合は、無効なシフトと呼びます。あなたの仕事は、与えられたテキストTとパターンPのvaldシフトの数を計算することです。

説明を入力してください

いずれの場合も、1行に2つの文字列TとPがあり、1つのスペースで区切られています。TとPの両方の長さが10 ^ 6を超えないと想定できます。

出力の説明:

別の行に数値を出力する必要があります。これは、指定されたテキストTとパターンPの有効なシフトの数を示します。

回答

#include<iostream>
#include<string>
#include<vector>
using namespace std;

const int MAXN = 1000 + 10;

void getnext(int next[], string t) {
    
    
	int k = -1, j = 0;
	next[0] = -1;
	while (j < t.length() -1 )
		if (k == -1 || t[k] == t[j])
			next[++j] = ++k;
		else
			k = next[k];
	return;
}

int KMP(string text,string t,int next[]) {
    
    
	int i = 0, j = 0;
	int count = 0;
	while (i < (int)(text.length()) && j < (int)(t.length())) {
    
    	
	//注意一定要加强制类型转换,length()返回的是无符号数,若不加当j=-1,比较的时候j被转为无符号数,会变得很大,导致bug
		if (j == -1 || text[i] == t[j]) {
    
    
			i++;
			j++;
		}
		else
			j = next[j];
		if (j == t.length()) {
    
    
			i = i - j + 1;
			j = 0;
			count++;
		}
	}
	return count;
}

int main() {
    
    
	string text, pattern;
	while (cin >> text >> pattern) {
    
    
		int next[MAXN];
		getnext(next, pattern);
		cout << KMP(text, pattern, next) << endl;
	}
	return 0;
}

STLのfind()を使用すると非常に便利ですが、今日KMPアルゴリズムの学習を終えたばかりであり、それでも手動で実装したいと考えています。stringのlength()は符号なしの数値を返します。これは本当にばかげています。長い間考えた後、私はそれを理解していません。

おすすめ

転載: blog.csdn.net/weixin_44897291/article/details/112966064