#POJ 2752名声を求め、(KMP)の名前をシーク

説明

小さな猫は、とても有名ですBytelandに丘や谷に比べて多くのカップルが不定期こと、そして彼らの新たに生まれた赤ちゃんに名前を与えるために小さな猫を尋ねました。彼らは名前を追求すると同時に、名声を求めています。そのような退屈な仕事から脱出するためには、革新的な小さな猫は簡単ですが、幻想的なアルゴリズムを動作します:

ステップ1を。新しい文字列Sに、父親の名前と母親の名前を接続します
ステップ2。(接頭辞が、また、Sの接尾辞だけではありません)Sの適切な接頭接尾文字列を検索します。

例:父= 'ALA'、母= 'ラ'、我々は+ 'ラ' = 'alala' 'たala' S =を持っています。Sの電位接頭接尾文字列は{ 'A'、 'ALA'、 'alala'}です。文字列Sを考えると、あなたは小さな猫がSの可能接頭接尾辞の文字列の長さを計算するプログラムを作成するのに役立つだろうか?(彼はあなたの赤ちゃんの名前を与えることによって、あなたに感謝かもしれません:)

入力

入力は、テストケースの数が含まれています。各テストケースは、Sは、上述した文字列を含む単一の行を占めています。

制限事項:小文字のみを入力して表示されることがあります。1 <= S <= 400000の長さ。

出力

各テストケースのために、出力新しい赤ちゃんの名前の可能な長さを表す、昇順の整数番号の一行。

サンプル入力

ababcababababcabab
aaaaa

サンプル出力

2 4 9 18 
1 2 3 4 5

 タイトル効果:入力文字列、サフィックスに等しく、すべてのプレフィックス長の出力。

アイデア:私はちょうど見始めたときまず、接頭辞と接尾辞最大の公共の長さを表すが、この質問は同じではありません次のアレイでKMPの役割は、彼は、すべてのプレフィックスサフィックスの長さに等しい出力ではなく、最大の長さであってもよいですアイデアは、テーブルの列の配列を試す彼の次の、その後、ではないことを、我々は発見しました。

例えば、私が対応する、「ababcababababcabab」を入力した答えはすべての答えは、それに含まれていないもので、「001201234343456789」を見ているのですか?再び役割の次の配列を考えて、私は次のものが接頭辞と接尾辞の全体が同じような状況ではないことを示し、0の最後の配列であれば、私、共通接頭辞と接尾辞の最大長さまであり、とてもダイレクト出力に彼の長さ良い、全体の長さlen、LEN] [次の場合を表して!= 0は、その後、その0から次クロスストリング[LEN]を意味し、LEN - LEN []次の断面llenに同じであるが、彼の==サフィックスプレフィックス長よりも小さく、のみとすることができます次は、次の長さの前で[lenの]?[レン]は次です!次の文字列[LEN] [アイテムのlen後の次の項目]の前に、この時点で等しく、これだけ人のように、あなたは、前のセクションとバックの他の部分を見ることができますし、再度、これは再帰的なプロセスであるため、ロープをカットし、半日のように、前半と後半は同じであるので、彼はもはや切断することが可能になるまでの半分が読むことはできませんした後、それが^ _ ^下に理解されるべきです

ACコード:

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 4e5 + 5;

string line;
int nxt[maxn], pre[maxn];
void getnext() {
    nxt[0] = -1;
    int i = 0, j = -1;
    while (i < line.size()) {
        if (j == -1 || line[i] == line[j])
            nxt[++i] = ++j;
        else
            j = nxt[j];
    }
}

int main()
{
    while (cin >> line) {
        memset(nxt, 0, sizeof(nxt));
        memset(pre, 0, sizeof(pre));
        getnext();
        int len_ = line.size();
        int ans = nxt[len_], X = 0;len_;
        if (!ans) {cout << len_ << endl; continue;}  // 自己就是循环体的情况
        pre[X++] = len_, pre[X++] = ans;  //把自己先存进去
        while (nxt[ans] != 0) {  //当不能再被截
            pre[X++] = nxt[ans];
            ans = nxt[ans];
        }
        for (int i = X - 1; i >= 0; i--) cout << pre[i] << " ";
        cout << endl;
    }
    return 0;
}

 

 

おすすめ

転載: blog.csdn.net/weixin_43851525/article/details/91903191