BZOJ 2806 Luogu P4022 [CTSC2012] Cheat (generalized suffix automaton, DP, half, monotonously queue)

Topic links: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806
(luogu) https://www.luogu.org/problemnew/show/P4022

Solution: to "make the library" in the string to build broad SAM. (Add # feel the pieces together directly SAM line ah, but the constant big point, but we all write I will follow the broad SAM SAM write a generalized 233,333)

When asked binary \ (L \) , seeking the least mismatches becomes several locations. DP equations are then \ (DP [I] = \ min (DP [-I. 1] + 1'd, \ I-match min_ {[I] \ Le J \ iL} Le DP [J]) \) . Wherein \ ( match [j] \) represented by \ (J \) sub-end length of the longest string of matches, with a suffix automaton obtained. Monotone to queue optimization.

Should a[i]-=96I write a[i]-=48; dp after the expiry does not update ans; Anti-half points ...... I was more brainless

Note that a problem is that, because here (MID \) \ limited only \ (\ le i-mid \ ) position in order to be put into monotone queue, can not put up a \ (0 \) into them!

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1.1e6;
const int S = 2;
int son[(N<<1)+3][S+1];
int fa[(N<<1)+3];
int len[(N<<1)+3];
char a[N+3];
char b[N+3];
int match[N+3];
int dp[N+3];
int dq[N+3];
int n,m,siz,rtn,lstpos;

void initSAM()
{
    siz = rtn = lstpos = 1;
}

void insertchar(char ch)
{
    int p = lstpos,np; siz++; np = lstpos = siz; len[np] = len[p]+1;
    for(; p && son[p][ch]==0; p=fa[p]) {son[p][ch] = np;}
    if(!p) {fa[np] = rtn;}
    else
    {
        int q = son[p][ch];
        if(len[q]==len[p]+1) {fa[np] = q;}
        else
        {
            siz++; int nq = siz; len[nq] = len[p]+1;
            memcpy(son[nq],son[q],sizeof(son[q]));
            fa[nq] = fa[q]; fa[np] = fa[q] = nq;
            for(; p && son[p][ch]==q; p=fa[p]) {son[p][ch] = nq;}
        }
    }
}

int main()
{
    initSAM();
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        lstpos = rtn;
        scanf("%s",a+1); int lena = strlen(a+1);
        for(int j=1; j<=lena; j++) {insertchar(a[j]-48);}
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%s",a+1); int lena = strlen(a+1);
        for(int j=1; j<=lena; j++) {a[j]-=48;}
        int u = rtn,cur = 0;
        for(int j=1; j<=lena; j++)
        {
            while(u && son[u][a[j]]==0) {u = fa[u]; cur = len[u];}
            if(son[u][a[j]]) {u = son[u][a[j]]; cur++;}
            else {u = rtn; cur = 0;}
            match[j] = cur;
        }
        int left = 0,right = lena,mid,ans;
        while(left<right)
        {
            mid = (left+right+1)>>1;
            dp[0] = 0; int head = 1,tail = 0;
            if(mid<=1) {tail++; dq[tail] = 0;}
            for(int j=1; j<=lena; j++)
            {
                dp[j] = dp[j-1]+1;
                while(head<=tail && dq[head]<j-match[j]) {dq[head] = 0; head++;}
                if(head<=tail)
                {
                    dp[j] = min(dp[j],dp[dq[head]]);
                }
                if(j-mid+1>=0)
                {
                    while(head<=tail && dp[dq[tail]]>=dp[j-mid+1]) {dq[tail] = 0; tail--;}
                    tail++; dq[tail] = j-mid+1;
                }
            }
            ans = dp[lena];
            if(ans*10<=lena) {left = mid;}
            else {right = mid-1;}
        }
        printf("%d\n",left);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11071957.html