【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条边的方案数,那么有 ...
随机推荐
- mongoDB与sql聚合操作对应图
SQL Terms, Functions, and Concepts MongoDB Aggregation Operators WHERE $match GROUP BY $group HAVING ...
- WPF:ComboBox使用XmlDataProvider做级联
程序功能: 使用ComboBox做级联,数据源为XML文件,适合小数据量呈现 程序代码: <Window x:Class="WpfApplication1.LayouTest" ...
- 【CodeForces】913 F. Strongly Connected Tournament 概率和期望DP
[题目]F. Strongly Connected Tournament [题意]给定n个点(游戏者),每轮游戏进行下列操作: 1.每对游戏者i和j(i<j)进行一场游戏,有p的概率i赢j(反之 ...
- Kali设置代理
原文:Kali-linux设置ProxyChains ProxyChains是Linux和其他Unices下的代理工具.它可以使任何程序通过代理上网,允许TCP和DNS通过代理隧道,支持HTTP.SO ...
- 重载jquery on方法实现click事件在移动端的快速响应
额,这个标题取的还真是挺装的... 其实我想表达的是jquery click事件如何在移动端自动转换成touchstart事件. 因为移动端click事件会比touchstart事件慢几拍 移动设备某 ...
- Angular 2.0 基础:服务
什么是服务(Service) 在Angular 2 中我们提到的服务 service 一般指的是 哪些能够被其他组件或者指令调用的 单一的,可共享的 代码块.当然,通过服务可以将数据和组件分开,这样就 ...
- jquery 生成二维码
jquery的二维码生成插件qrcode,在页面中调用该插件就能生成对应的二维码 <!DOCTYPE html> <html> <head> <meta ch ...
- MGR Switch Muti-Primary to single_primary
MGR Muti-Primary 切换 single_primary 模式 原因:因为希望做ProxySQL+MGR之间Proxy层的消耗测试,需要把原有的MGR多主改为单主模式. 修改MGRgrou ...
- Spring Boot 在接收上传文件时,文件过大异常处理问题
Spring Boot 在接收上传文件时,文件过大时,或者请求过大,spring内部处理都会抛出异常,并且捕获不到. 虽然可以通过调节配置,增大 请求的限制值. 但是还是不太方便. 之所以捕获不到异常 ...
- mybatis注解使用
spring整合mybatis时,要使用mybatis的注解,需要spring-config.xml文件中添加下述配置: <!--下述配置指明了我们的Mapper,即Dao,在相应的包里也就可以 ...