7-8良い接尾辞(10ポイント)
文字列のサフィックスは、次の条件を満たす場合に適切なサフィックスと呼ばれます。
(1)文字列に少なくとも2回出現します。
(2)条件(1)を満たす最長のもの。
文字列の適切な接尾辞の長さを計算するプログラムを作成してください。文字列をそれ自体の接尾辞と呼ぶことはできないことに注意してください。
入力と出力の説明
入力フォーマット:
入力は、10 ^ 5文字以下の文字列です。
出力フォーマット:
出力は整数であり、入力文字列の適切なサフィックスの長さを表します。
サンプル
入力例1:
xacbacba
出力例1:
4
入力例2:
yxxabacaba
出力例2:
3
入力例3:
abc
出力サンプル3:
0
問題解決
プレフィックス関数の定義を最初に見てください。定義に
よれば、next [i] = k; kは、iを末尾の添え字とする、サブストリング内の最長の同じ真のプレフィックスとサフィックスの長さです。したがって、この質問は最初に逆になります。文字列、そして次に最大の次の[i]問題を尋ねます
コード
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1e5 + 2;
char str[maxn];
int next_[maxn];
int ans;
void get_next(int next_[], char str[]) {
int len = strlen(str);
next_[0] = 0;
for (int i = 1; i < len; i++) {
/*j表示上一个匹配的长度, j - 1就是j长度的前缀的末尾下标*/
int j = next_[i - 1];
/*如果不匹配, j == 0 或 不匹配时退出循环*/
while (j > 0 && str[i] != str[j]) j = next_[j - 1]; //向前回溯查找
if (str[i] == str[j]) j++; //能够匹配
next_[i] = j;
ans = max(ans, j);
}
}
int main() {
scanf("%s", str);
reverse(str, str + strlen(str));
get_next(next_, str);
// for (int i = 0; i < strlen(str); i++) {
// printf("%d ", next_[i]);
// }
printf("%d\n", ans);
system("pause");
return 0;
}