【BZOJ-4180】字符串計數 後綴自動機 + 矩陣乘法

4180: 字符串計數

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 146  Solved: 66
[Submit][Status][Discuss]

Description

SD有一名神犇叫作Oxer,他以爲字符串的題目都太水了,因而便出了一道題來虐蒟蒻yts1999。
 
他給出了一個字符串T,字符串T中有且僅有4種字符 'A', 'B', 'C', 'D'。如今他要求蒟蒻yts1999構造一個新的字符串S,構造的方法是:進行屢次操做,每一次操做選擇T的一個子串,將其加入S的末尾。
 
對於一個可構造出的字符串S,可能有多種構造方案,Oxer定義構造字符串S所需的操做次數爲全部構造方案中操做次數的最小值。
 
Oxer想知道對於給定的正整數N和字符串T,他所能構造出的全部長度爲N的字符串S中,構造所需的操做次數最大的字符串的操做次數。
 
蒟蒻yts1999固然不會作了,因而向你求助。

Input

第一行包含一個整數N,表示要構造的字符串長度。
 
第二行包含一個字符串T,T的意義如題所述。

Output

輸出文件包含一行,一個整數,爲你所求出的最大的操做次數。

Sample Input

5
ABCCAD

Sample Output

5

HINT

【樣例說明】

例如字符串"AAAAA",該字符串所需操做次數爲5,不存在能用T的子串構造出的,且所需操做次數比5大的字符串。

【數據規模和約定】

對於100%的數據,1 ≤ N ≤ 10^18,1 ≤ |T| ≤ 10^5。

Source

By yts1999php

Solution

人傻不會作...因而看的題解...ios

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define LL long long
#define MAXN 500010
#define INF (1LL<<62) 
 
LL N;
char S[MAXN];
 
int last=1,sz=1,root=1,par[MAXN<<1],len[MAXN<<1],son[MAXN][4];
LL f[MAXN][4];
inline void Extend(int c)
{
    int cur=++sz,p=last;
    len[cur]=len[p]+1;
    while (p && !son[p][c]) son[p][c]=cur,p=par[p];
    if (!p) par[cur]=root;
    else {
        int q=son[p][c];
        if (len[p]+1==len[q]) par[cur]=q;
        else {
            int nq=++sz;
            memcpy(son[nq],son[q],sizeof(son[nq]));
            len[nq]=len[p]+1; par[nq]=par[q];
            while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
            par[q]=par[cur]=nq;
        }
    }
    last=cur;
}
 
bool visit[MAXN<<1];
inline void Dfs(int now)
{
    if (visit[now]) return;
    visit[now]=1;
    for (int c=0; c<4; c++)
        if (son[now][c]) 
            Dfs(son[now][c]),f[now][c]=INF;
        else f[now][c]=1;
    for (int c=0; c<4; c++)
        if (son[now][c])
            for (int cc=0; cc<4; cc++)
                f[now][cc]=min(f[now][cc],f[son[now][c]][cc]+1);
}
 
struct Matrix{
    LL a[4][4];
    Matrix() {for (int i=0; i<4; i++) for (int j=0; j<4; j++) a[i][j]=INF;}
    LL* operator [](int x) {
        return a[x];
    }
}X;
 
Matrix operator * (Matrix &A,Matrix &B) {
    Matrix C;          
    for (int i=0; i<4; i++)
        for (int j=0; j<4; j++)
            for (int k=0; k<4; k++)
                C[i][j]=min(C[i][j],A[i][k]+B[k][j]);
    return C;
}
 
Matrix operator ^ (Matrix x,LL y) {
    Matrix re;
    memset(re.a,0,sizeof(re.a));
    for (int i=0; i<4; i++) re[i][i]=1;
    for ( ; y; y>>=1,x=x*x) if (y&1) re=re*x;
    return re;
}
 
inline bool check(LL x)
{
    Matrix B=X^x;   
    for (int i=0; i<4; i++)
        for (int j=0; j<4; j++)
            if (B[i][j]+1<=N) return 1;
    return 0; 
}
 
int main()
{
    scanf("%lld%s",&N,S+1); int L=strlen(S+1);
     
    for (int i=1; i<=L; i++) Extend(S[i]-'A');
     
    Dfs(root);
     
    for (int i=0; i<4; i++)
        for (int j=0; j<4; j++)
            X[i][j]=f[son[root][i]][j];
     
//  for (int i=0; i<4; i++,puts(""))
//      for (int j=0; j<4; j++) printf("%I64d  ",X[i][j]==INF? -1:X[i][j]);
     
    LL l=0,r=N+1,mid,ans=0;
    while (l<=r) {
        mid=(l+r)>>1;
        if (check(mid)) l=mid+1;
            else r=(ans=mid)-1;
    }
    printf("%lld\n",ans);
     
    return 0;
}
/*
5
ABCCAD
*/
相關文章
相關標籤/搜索