【BZOJ 4180】 4180: 字符串计数 (SAM+二分+矩阵乘法)
4180: 字符串计数
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 164 Solved: 75Description
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
ABCCADSample Output
5HINT
【样例说明】例如字符串"AAAAA",该字符串所需操作次数为5,不存在能用T的子串构造出的,且所需操作次数比5大的字符串。【数据规模和约定】对于100%的数据,1 ≤ N ≤ 10^18,1 ≤ |T| ≤ 10^5。Source
【分析】
好题啊。我没想到。。
要用一种稍微转化一下的思维?
要算n最多操作次数,可以二分答案,然后询问操作次数为x的区间最小长度是多少。【我个人觉得这样想也不简单啊。
考虑如果S确定的话,其实是贪心的,匹配到不能匹配的时候断掉,成为新的一段。
在SAM上就是没有儿子的后继之后,就跳回根。
所以其实(10^18的时候你应该看出来要矩乘了),矩阵中不需要存SAM的每个点,也不能存,只要存现在是什么颜色就好了。
保证断掉的话,就是f[i][j]表示第i为开头的子串最短多少后面接j就会断。
这个很好求,先做SAM,求出mn[x][i]表示x这个点后面接最短多少的子串再接j之后就会断。
mn[x][i]=min(mn[son][i]+1)。
f[i][j]=mn[1的i儿子][j]。
然后x次操作就是f[i][j]^x,矩阵“乘法”的运算实际上是求和取min。
【看代码吧!
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 100010
#define LL long long
#define INF 0xfffffff
#define inf 1LL<<60 LL n;
int mymin(int x,int y) {return x<y?x:y;} struct node
{
int pre,son[],step;
}t[Maxn*];
bool vis[*Maxn]; int mn[*Maxn][]; struct sam
{
int last,tot;
void extend(int k)
{
int np=++tot,p=last;
t[np].step=t[p].step+;
while(p&&!t[p].son[k])
{
t[p].son[k]=np;
p=t[p].pre;
}
if(!p) t[np].pre=;
else
{
int q=t[p].son[k];
if(t[q].step==t[p].step+) t[np].pre=q;
else
{
int nq=++tot;
memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
t[nq].step=t[p].step+;
t[nq].pre=t[q].pre;
t[q].pre=t[np].pre=nq;
while(p&&t[p].son[k]==q)
{
t[p].son[k]=nq;
p=t[p].pre;
}
}
}
last=np;
}
void dfs(int x)
{
if(vis[x]) return;
vis[x]=;
for(int i=;i<=;i++) mn[x][i]=INF;
for(int i=;i<=;i++)
{
if(!t[x].son[i]) mn[x][i]=;
else
{
dfs(t[x].son[i]);
for(int j=;j<=;j++) mn[x][j]=mymin(mn[x][j],mn[t[x].son[i]][j]+);
}
}
}
}sam; char s[Maxn]; struct Matrix
{
LL w[][];
Matrix() {memset(w,,sizeof(w));}
inline friend Matrix operator * (const Matrix A,const Matrix B)
{
Matrix ret;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
ret.w[i][j]=inf;
for(int k=;k<=;k++) ret.w[i][j]=min(ret.w[i][j],A.w[i][k]+B.w[k][j]);
}
return ret;
}
inline friend Matrix operator ^ (const Matrix A,LL k)
{
Matrix ret,tmp=A;
for(int i=;i<=;i++) for(int j=;j<=;j++) ret.w[i][j]=(i==j)?:;
for (;k;k>>=,tmp=tmp*tmp) if(k&) ret=ret*tmp;
return ret;
}
}Q; bool check(LL x)
{
Matrix B=Q^x;
LL mn=inf;
for(int i=;i<=;i++) for(int j=;j<=;j++) mn=min(mn,B.w[i][j]);
return mn>=n;
} int main()
{
scanf("%lld",&n);
scanf("%s",s);
int ll=strlen(s);
sam.tot=sam.last=;
for(int i=;i<ll;i++) sam.extend(s[i]-'A'+);
memset(vis,,sizeof(vis));
sam.dfs(); for(int i=;i<=;i++) for(int j=;j<=;j++) Q.w[i][j]=mn[t[].son[i]][j]; LL l=,r=n,ans;
while(l<r)
{
LL mid=(l+r)>>;
if(check(mid)) r=mid;
else l=mid+;
}
printf("%lld\n",r);
return ;
}
看了CA爷的代码,感觉我的矩乘好看多啦!
写在结构体里面很有条理!!
2017-04-17 20:02:16
【BZOJ 4180】 4180: 字符串计数 (SAM+二分+矩阵乘法)的更多相关文章
- BZOJ4180:字符串计数(SAM,二分,矩阵乘法)
Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C', ...
- BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)
Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...
- 【BZOJ-4180】字符串计数 后缀自动机 + 矩阵乘法
4180: 字符串计数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 146 Solved: 66[Submit][Status][Discuss] ...
- BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法
标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...
- BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)
首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...
- 【BZOJ 2510】 2510: 弱题 (矩阵乘法、循环矩阵的矩阵乘法)
2510: 弱题 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 374 Solved: 196 Description 有M个球,一开始每个球均有一 ...
- POJ 3233 Matrix Power Series 二分+矩阵乘法
链接:http://poj.org/problem?id=3233 题意:给一个N*N的矩阵(N<=30),求S = A + A^2 + A^3 + - + A^k(k<=10^9). 思 ...
- 【BZOJ】2875: [Noi2012]随机数生成器(矩阵乘法+快速乘)
http://www.lydsy.com/JudgeOnline/problem.php?id=2875 矩阵的话很容易看出来.....我就不写了.太水了. 然后乘法longlong会溢出...那么我 ...
- BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)
题目链接 比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边 如果这样表示是不好转移的 可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 ...
随机推荐
- 【转】ubuntu 11.04使用apt-get安装软件时一直提示E:unable to locate package
问题: VMware虚拟机安装了ubuntu 11.04,在使用apt-get安装软件时一直提示E:Unable to locate package. 百度了原因,说是要更新源,使用命令:sudo a ...
- ① 设计模式的艺术-07.适配器(Adapter)模式
什么是适配器模式? 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 模式中的角色 目标接口(Target):客户所期待的接口 ...
- laravel前台html代码不显示
后天向前台传输变量,如果能取到变量数据,还有代码,但是不显示图片 可以把{{}}换成{!! !!}试试.
- Oracle笔记之约束
约束用于保证数据库中某些数据的完整性,给某一列添加一个约束可以保证不满足约束的数据是绝对不会被接受的. 约束主要有那么五种类型:非空约束.唯一约束.主键约束.外键约束.校验约束. 使用如下命令检索某个 ...
- pythonif语句和循环语句
1.if语句用法 # if语句用法(缩进相同的成为一个代码块) score=90 if score>=60: print("合格") print("OK" ...
- onvif客户端
前言 做开发有8年时间了,ffmpeg和onvif与我是特别有缘的了(说着玩的,我更认为是因为他们确实强大^_^). ffmpeg在毕业设计时就有用到,5年后做windows.linux播放库时又有用 ...
- 64_t5
texlive-mkpattern-svn15878.1.2-33.fc26.2.noarch..> 24-May-2017 15:54 38178 texlive-mkpic-bin-svn3 ...
- (总结)MySQL自带的性能压力测试工具mysqlslap详解
PS:今天一同事问我有木有比较靠谱的mysql压力测试工具可用.其实mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的.下面举例说说.mysqlslap是从5.1.4版开始的一 ...
- php cache类代码(php数据缓存类)
如果访问量大的话会给数据库造成很大的负担,所以对于变化不经常的内容要做好php 数据cache(缓存)是十分必要的,我做了一个简单的php“文件缓存”的类,希望对大家有所帮助. 思路是这样的: 对于一 ...
- 看看PHP迭代器的内部执行过程
class myIterator implements Iterator { private $position = 0; private $array = array( "first_el ...