Cyclical Quest CodeForces - 235C (suffix automaton)

Cyclical Quest

\[ Time Limit: 3000 ms\quad Memory Limit: 524288 kB \]

The meaning of problems

Given a string of \ (S \) string, followed \ (T \) query, a given enumerated \ (T \) string, obtains \ (T \) in all cycles substring \ ( S \) number string appears.

Thinking

For each query string, because the substring all cycles, so you can put \ (t \) string to the end of the copy, and then to seek \ (LCS \) .

  • If \ (P \) node queried \ (TLEN the LCS == \) , then the \ (P \) substring represented on the condition comprises one cycle \ (T \) string.
  • If \ (the LCS> TLEN \) , it shows \ (P \) comprises a loop \ (T \) string, but longer than the cycle match \ (T \) string, then the string must contribution thereof \ (father \) on, so we make a temporary variable \ (tmp \) to \ (father \) jump to find the contribution of this string.
  • Finally, as long as the calculated number of occurrences of each node contains a substring, and these values ​​satisfy the condition on it together.

Here we find \ (LCS \) directly with the intermediate variables \ (res \) to instead of \ (father \) update. For example, I now node \ (u \) , and \ (Father [the p-] = U \) , so \ (p \) in \ (u \) is \ (LCS \) even more, \ (u \) to its \ (father \) update process in fact and \ (p \) to \ (father \) update process is the same, the final will stay in the same node, while the contribution of a node as long counted once, so the \ ( u \) in fact may not be up updated.

This problem has also query \ (1E5 \) , and the total length of inquiry was \ (1e6 \) , it may be many and each query string short occurs, so the \ (vis \) Every time I go \ ( memset \) will \ (TLE \) of cynicism ...

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e6 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

struct Sam {
    int node[maxn<<1][27], step[maxn<<1], fa[maxn<<1];
    int dp[maxn<<1], tax[maxn<<1], gid[maxn<<1];
    int vis[maxn<<1];
    int last, sz;
    int newnode() {
        mes(node[++sz], 0);
        dp[sz] = step[sz] = fa[sz] = 0;
        return sz;
    }
    void init() {
        sz = 0;
        last = newnode();
    }
    void insert(int k) {
        int p = last, np = last = newnode();
        dp[np] = 1;
        step[np] = step[p]+1;
        for(; p&&!node[p][k]; p=fa[p])
            node[p][k] = np;
        if(p==0) {
            fa[np] = 1;
        } else {
            int q = node[p][k];
            if(step[q] == step[p]+1) {
                fa[np] = q;
            } else {
                int nq = newnode();
                memcpy(node[nq], node[q], sizeof(node[q]));
                fa[nq] = fa[q];
                step[nq] = step[p]+1;
                fa[np] = fa[q] = nq;
                for(; p&&node[p][k]==q; p=fa[p])
                    node[p][k] = nq;
            }
        }
    }
    void handle() {
        for(int i=0; i<=sz; i++)    tax[i] = 0;
        for(int i=1; i<=sz; i++)    tax[step[i]]++;
        for(int i=1; i<=sz; i++)    tax[i] += tax[i-1];
        for(int i=1; i<=sz; i++)    gid[tax[step[i]]--] = i;
        for(int i=sz; i>=1; i--) {
            int u = gid[i];
            dp[fa[u]] += dp[u];
        }
    }
    int solve(char *s, int len, int id) {
        int p = 1, res = 0;
        int ans = 0;
        for(int i=1; i<=len+len; i++) {
            int k = s[i]-'a'+1;
            while(p && !node[p][k]) {
                p = fa[p];
                res = step[p];
            }
            if(p == 0) {
                p = 1;
                res = 0;
            } else {
                p = node[p][k];
                res++;
                if(res >= len) {
                    int tmp = p;
                    while(vis[tmp]!=id &&!(step[fa[tmp]]+1<=len && len<=step[tmp])) {
                        vis[tmp] = id;
                        tmp = fa[tmp];
                    }
                    if(vis[tmp] != id) {
                        vis[tmp] = id;
                        ans += dp[tmp];
                    }
                }
            }
        }
        return ans;
    }
} sam;
char s[maxn], t[maxn<<1];

int main() {
    scanf("%s", s+1);
    int slen = strlen(s+1);
    sam.init();
    for(int i=1; i<=slen; i++) {
        sam.insert(s[i]-'a'+1);
    }
    sam.handle();
    scanf("%d", &T);
    for(int tt=1; tt<=T; tt++) {
        scanf("%s", t+1);
        int tlen = strlen(t+1);
        for(int i=1; i<=tlen; i++) {
            t[i+tlen] = t[i];
        }
        t[tlen+tlen+1] = '\0';
        int ans = sam.solve(t, tlen, tt);
        printf("%d\n", ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Jiaaaaaaaqi/p/10995680.html