【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条边的方案数,那么有 ...
随机推荐
- webDriver检索table数据
最近在做爬虫相关工作,用到了webdriver,记录一些遇到的问题和解决方法: 如何查找 table中的行 例如: <div id="a"> <table cla ...
- WPF:ComboBox使用XmlDataProvider做级联
程序功能: 使用ComboBox做级联,数据源为XML文件,适合小数据量呈现 程序代码: <Window x:Class="WpfApplication1.LayouTest" ...
- 【BZOJ】2599: [IOI2011]Race 点分治
[题意]给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000.注意点从0开始编号,无解输出-1. [算法]点分治 [题解] ...
- mongoose使用简记
mongodb中集合相当于表,常用指令 mongo 进入数据库 use yourdatabase 来选择你的数据集,这个跟关系型中的一样 show collections 来查看你数据集中的表,col ...
- 基于canvas的图片编辑合成器
在我们日常的前端开发中,经常会要给服务器上传图片,但是局限很大,图片只能是已有的,假设我想把多张图片合成一张上传就需要借助图片编辑器了,但是现在我们有了canvas合成就简单多了 首先我们看图片编辑器 ...
- JavaScript三种绑定事件的方式
JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...
- windows 10添加定时任务
1.在搜索栏搜索‘任务计划’ 2.选择任务计划程序,打开 3.创建基本任务 4.输入任务名称 5.选择任务触发周期 6.选择任务触发的具体时间点 7.选择任务需要做的事 8.选择启动程序后,选择具体的 ...
- MySQL 作业题及答案
MySQL 测试题 一. 表关系: 请创建如下表,并创建相关约束 创建表sql如下: /* Navicat MySQL Data Transfer Source Server : 192.168.11 ...
- charles抓包误点deny处理办法及日常抓包
误点deny方法在最底下~~ (博文为转载) 我们在开发网站项目的时候,我们可以通过浏览器的debug模式来看request以及response的数据,那么如果我们开发移动端项目没有网页呢?如何抓取数 ...
- GPS位置模拟-安卓
测试定位功能时都需要位置模拟,一般有如下3种方式: a)手机上安装第三方模拟软件:需要Root: b)PC模拟其中运行app并模拟位置:不能在真机上运行,手机兼容性不能测试到: b)在app中让开发增 ...