[bzoj3670][uoj5][Noi2014]动物园【kmp】

【题目链接】
  https://www.lydsy.com/JudgeOnline/problem.php?id=3670
  http://uoj.ac/problem/5
【题解】
  kmp做两遍,第一遍求出next,第二遍与第一遍差不多,在kmp的时候多一个不超过1/2的条件。
  时间复杂度 O ( N )
  然而我一开始做的时候没有想到,写了一个瞎搞的暴力,竟然能过现场的全部数据。
【代码】

/* - - - - - - - - - - - - - - -
    User :      VanishD
    problem :   [bzoj3670][uoj5][noi2014]
    Points :    kmp
- - - - - - - - - - - - - - - */
# include <bits/stdc++.h>
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    N       1000100
# define    P       1000000007
using namespace std;
int read(){
    int tmp = 0, fh = 1; char ch = getchar();
    while (ch < '0' || ch > '9'){ if (ch == '-') fh = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9'){ tmp = tmp * 10 + ch - '0'; ch = getchar(); }
    return tmp * fh;
}
struct Edge{
    int data, next;
}e[N];
ll ans;
int nex[N], head[N], place, st[N], top, cnt[N], use[N];
char s[N];
void build(int u, int v){
    e[++place].data = v; e[place].next = head[u]; head[u] = place;
}
void dfs(int x, int fa, int p){
    st[++top] = x; use[x] = true;
    while (x / 2 >= st[p + 1]) p++;
    cnt[x] = p;
    for (int ed = head[x]; ed != 0; ed = e[ed].next)
        if (e[ed].data != fa)
            dfs(e[ed].data, x, p);
    top--; 
}
int main(){
//  freopen(".in", "r", stdin);
//  freopen(".out", "w", stdout);
    for (int opt = read(); opt--;){
        scanf("\n%s", s + 1);
        int len = strlen(s + 1);
        nex[1] = 0;
        for (int i = 2; i <= len; i++){
            int p = i - 1;
            while (p != 0 && s[nex[p] + 1] != s[i]) 
                p = nex[p];
            if (p == 0) nex[i] = 0;
                else nex[i] = nex[p] + 1;
        }
        memset(head, 0, sizeof(head));
        memset(cnt, 0, sizeof(cnt));
        memset(use, 0, sizeof(use));
        place = 0;
        for (int i = 1; i <= len; i++)
            if (nex[i] != 0) build(nex[i], i);
        for (int i = 1; i <= len; i++)
            if (!use[i]) dfs(i, 0, 0);
        ll ans = 1;
        for (int i = 1; i <= len; i++)
            ans = ans * (cnt[i] + 1) % P;
        printf("%lld\n", ans);
    } 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/d_vanisher/article/details/80566849
今日推荐