Luogu 2375 [NOI2014]动物园

字胡串什么的一直不太会,感觉这题…还蛮本质的
考虑暴力求解:num[i]相当于从一直跳nxt,如果nxt[j] * 2 <= i 那么就累加答案

其实这是一个树的结构,也就是说跳到一个结点满足条件,那么它上面的结点一定都满足,所以在求nxt的时候顺便递推一下每一个结点的答案,那么模拟一下匹配nxt的过程,只要跳到第一个j * 2 <= i 就可以算答案了
不会算时间复杂度QuQ

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const int N = 1e6 + 5;
const ll mod = 1e9 + 7;

int testCase, n, nxt[N];
ll num[N];
char s[N];

int main() {
    for(scanf("%d", &testCase); testCase--; ) {
        scanf("%s", s + 1);
        n = strlen(s + 1);
        
        memset(nxt, 0, sizeof(nxt));
        memset(num, 0, sizeof(num));
        num[1] = 1;
        for(int i = 2, j = 0; i <= n; i++) {
            for(; j > 0 && s[j + 1] != s[i]; j = nxt[j]);
            if(s[j + 1] == s[i]) j++;
            nxt[i] = j;
            num[i] = num[j] + 1LL;
        }
        
        ll ans = 1LL;
        for(int i = 2, j = 0; i <= n; i++) {
            for(; j > 0 && s[j + 1] != s[i]; j = nxt[j]);
            if(s[j + 1] == s[i]) j++;
            for(; (j * 2) > i; j = nxt[j]);
            ans = ans * (num[j] + 1)% mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/CzxingcHen/p/9466367.html