Description
Appleman and Toastman like games. Today they play a game with strings with the following rules. Firstly Toastman tells Appleman two strings s and t both consisting only of letters ‘A’, ‘B’, ‘C’, ‘D’. Then Appleman must build string s as quickly as possible. Initially he has empty string, and in one second he can append to end of the current string any contiguous substring of t.
Now, Toastman and Appleman are beginning to play the game. Toastman has already told string t to Appleman, but he hasn’t come up with string s yet. Toastman only thinks, that he should choose string s consisting of n characters. Of course, he wants to find the worst string for Appleman (such string, that Appleman will spend as much time as possible during the game). Tell Toastman, how much time will Appleman spend during the game if Toastman finds the worst string for him. You can assume that Appleman plays optimally, therefore he builds any string s in minimal possible time.
Input
The first line contains an integer n (1 ≤ n ≤ 1018). The second line contains string t (1 ≤ |t| ≤ 105). String t consists of only letters ‘A’, ‘B’, ‘C’, ‘D’. Each letter appears at least once in string t.
Output
Print a single integer — the largest possible time Appleman needs.
Examples
input
5
ABCCAD
output
5
input
5
AAABACADBABBBCBDCACBCCCDDDBDCDD
output
4
Note
In the first example, Toastman can choose s equal to “AAAAA”.
In the second example, Toastman can choose s equal to “DADDA”.
题目大意
需要你构造一个字符串s,使得用字符串t来拼s的次数最多。
每次,可以从t中取出连续的一段,加到s中去。
假设是最优策略。
题解
最终构造出来的字符串s一个是由无数段t中的连续的字符串构成的。
如果想让次数更多,那么尽可能使得每一个段最短。
设
fi,j
表示以i作为开头,在其结尾放j,并不会产生一个新的t的子串。
用倍增的思想将他们不断合并产生新的串。
求答案的时候就将这些串合并一下。
观察可以发现,trie只需要建深度为
log4n
的,剩下的是不可能成为最优解的。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 10000003
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define fori for(int i=0;i<4;i++)
#define forj for(int j=0;j<4;j++)
#define fork for(int k=0;k<4;k++)
using namespace std;
char ch;
void read(ll &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
int trie[N][4],T[N],tot,x,y,len;
ll log_4,t,n,f[5][5][80],g[5][5],ans,p[5][5],z[80],lim,mi;
bool now;
void dfs(int xx,int x,int y,int l)
{
if(l>=f[xx][y][0])return;
if(trie[x][y]==0)
{
f[xx][y][0]=l;
return;
}
fori if(trie[x][i])dfs(xx,trie[x][i],y,l+1);
}
int main()
{
read(n);
t=tot=1;
for(ch=G();ch<'A' || ch>'D';ch=G());
for(len=0;'A'<=ch && ch<='D';ch=G())T[++len]=ch-'A';
for(log_4=0;t*4<=len;log_4++)t=t<<2;
log_4++;
for(int i=1;i<=len;i++)
{
x=1;y=min(i+log_4-1,len);
for(int j=i;j<=y;x=trie[x][T[j]],j++)
if(trie[x][T[j]]==0)trie[x][T[j]]=++tot;
//write(tot);P('\n');
}
//build trie
fori forj f[i][j][0]=inf;
fori forj
if(trie[1][i] && trie[1][j])dfs(i,trie[1][i],j,1);
//初始化
//f[i('A'..'D')][j('A'..'D')] 以i开头,结尾后加上j,j不会被同一次覆盖,最短长度。
z[0]=1,z[1]=2;
for(int I=1;z[I]<=n;lim=I,I++)
{
z[I+1]=z[I]<<1;
fori forj fork
if(trie[1][i] && trie[1][j] && trie[1][k])
if(f[i][j][I]==0 || f[i][k][I-1]+f[k][j][I-1]<f[i][j][I])
f[i][j][I]=f[i][k][I-1]+f[k][j][I-1];
}
//倍增,不断合并两个串
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
printf("%d ",f[i][j][20]);
printf("\n");
}
now=1;
for(int I=lim;I>=0;I--)
{
mi=n<<1;
if(now)
{
fori forj
if(trie[1][i] && trie[1][j])
mi=min(mi,f[i][j][I]);
if(mi<n)
{
now=0;
ans+=z[I];
fori forj g[i][j]=f[i][j][I];
}
}
else
{
fori forj
{
p[i][j]=0;
fork
if(trie[1][i] && trie[1][j] && trie[1][k])
if(p[i][j]==0 || g[i][k]+f[k][j][I]<p[i][j])
p[i][j]=g[i][k]+f[k][j][I];
if(trie[1][i] && trie[1][j])mi=min(mi,p[i][j]);
}
if(mi<n)
{
ans+=z[I];
fori forj g[i][j]=p[i][j];
}
}
}
write(ans+1);
return 0;
}