【CF535D] TavasとMalekas题解

問題の意味の説明

それは空の長さを有している\(N- \)文字列\(ANS \)の長所与次いで、\(Mの\)シーケンス\(\)今シーケンスの各要素をする、(\しますa_iを\)所定の開始位置に指定された文字列持っている必要があります\(S \)をQ.文字列\(ANS \)が親切かもしれません。

ソリューション

主な考慮事項は可能です\(a_iを\)の直接出力で矛盾する結果との間で\(0 \)ので、私たちはすぐに現在の文字列を決定する必要があります\(複数可\)最初とテール一致しています。明らかに、2つの実行可能な解決策があり、最初のものはKMPあり、第二は、文字列のハッシュの形而上学です。しかしTaccaで問題にこのソリューションを書くことはないKMPをプレイしたいので、彼は、ハッシュを書きました。
ここでのハッシュは、単一のハッシュは、弾性率が、私が入るために開始することができ、本当にだった\(99844353 \) 目視検査は、素数ではないですが、でもQAQ後、交換した\(998 244 353 \) 彼はカードを見て恐れていませんでした)、結果は、使用するように決定決定的カード(試験31でWA)で\(19260817 \) 次いで、アウト。
文字列のハッシュ終了後の回答数の慣行についての判断のようなものを繰り返し、我々は統計的満足直接\(A_を{I + 1} -a_ {I}> LEN \) された\(A_ {私は+ 1} -a_ {I} -len \)数の合計が終了する特別な取扱い端に注意します。
そして、私たちはただの統計情報の数に設定している\(CNT \)番目に、答えは\(26 ^ {CNT} \) あなたは直接の暴力、最後取ることができ、でもパワープレーが速くていないノートの取り方を

コード

\(CH \)アレイは、文字列の上にある\(S \)
(P \)は\質問弾性率に応じて予め定められている
\(MOD \)ハッシュ係数であり、\(ベース\)はハッシュの基数であります
\(GETVAL \)機能を除去するために使用される\([L、R]を\ ) のハッシュ値

#include <cstdio>
#include <cstring>
#define p 1000000007

int read(){
    int x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}


char ch[1000005];
long long res[1000005];
long long fac[1000005];
const long long MOD = 9982442353ll;
const long long prime = 431ll;
const long long BASE = 131ll;

void getHash(int n){
    res[0] = 1; fac[0] = 1;
    for (int i = 1; i <= n; ++i)
        fac[i] = (fac[i - 1] * BASE) % MOD;
    for (int i = 1; i <= n; ++i)
        res[i] = (res[i - 1] * BASE + (ch[i] - 'A') * prime) % MOD;
}

inline long long getVal(int l, int r){
    return ((res[r] - ((res[l - 1] * fac[r - l + 1]) % MOD) + MOD) % MOD);
}

int a[1000005];

int main(){
    int n = read(), m = read();
    scanf("%s", ch + 1); 
    int len = strlen(ch + 1);
    if (!m){
        long long ans = 1;
        for (int i = 1; i <= n; ++i)
            (ans *= 26) %= p;
        printf("%lld", ans);
        return 0;
    }
    getHash(len);
    for (int i = 1; i <= m; ++i){
        a[i] = read();
        if (a[i] + len - 1 > n){
            puts("0");
            return 0;
        }
        if (i > 1 && a[i - 1] + len > a[i]){
            int x = a[i - 1] + len - a[i];
            if (getVal(len - x + 1, len) != getVal(1, x)){
                puts("0");
                return 0;
            }
        }
    }
    int cnt = a[1] - 1;
    for(int i = 1; i < m; i++){
        if(a[i] + len < a[i + 1]){
            cnt += a[i + 1] - a[i] - len;
        }
    }
    cnt += n - a[m] - len + 1;
    long long ans = 1;
    for (int i = 1; i <= cnt; ++i)
        (ans *= 26) %= p;
    printf("%lld", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/linzhengmin/p/11117508.html