【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 yts1999

Solution

人傻不会做...于是看的题解...

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
*/

  

posted @ 2017-03-27 15:44  DaD3zZ  阅读(473)  评论(0编辑  收藏