4180: 字符串计数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 164  Solved: 75

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

【分析】

  好题啊。我没想到。。

  要用一种稍微转化一下的思维?

  要算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+二分+矩阵乘法)的更多相关文章

  1. BZOJ4180:字符串计数(SAM,二分,矩阵乘法)

    Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C', ...

  2. BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)

    Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999.   他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...

  3. 【BZOJ-4180】字符串计数 后缀自动机 + 矩阵乘法

    4180: 字符串计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 146  Solved: 66[Submit][Status][Discuss] ...

  4. BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法

    标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...

  5. BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)

    首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...

  6. 【BZOJ 2510】 2510: 弱题 (矩阵乘法、循环矩阵的矩阵乘法)

    2510: 弱题 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 374  Solved: 196 Description 有M个球,一开始每个球均有一 ...

  7. 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). 思 ...

  8. 【BZOJ】2875: [Noi2012]随机数生成器(矩阵乘法+快速乘)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2875 矩阵的话很容易看出来.....我就不写了.太水了. 然后乘法longlong会溢出...那么我 ...

  9. BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)

    题目链接 比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边 如果这样表示是不好转移的 可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 ...

随机推荐

  1. DevExpress使用教程:GridView经验小结(官方中文文献经典资料技巧)

    下面是笔者自己总结的使用 DevExpress Gridview 的一些经验小结,分享给大家: 1.去除 GridView 头上的 "Drag a column header here to ...

  2. json格式的一些常用操作方法

    package com.liveyc.restfull.until; import java.util.HashMap; import java.util.Iterator; import java. ...

  3. jq消除网页滚动条

    网页有些时候需要能滚动的效果,但是不想要滚动条,我就遇到了这样的需求.自己用jq写了一个垂直滚动条. 纯css也可以实现 .box::-webkit-scrollbar{display:none} 但 ...

  4. mysql 创建数据库的时候选择 utf8 bin 和 utf8 ci的区别

    utf8 ci  不区分大小写: utf8 bin 区分大小写:

  5. Mysql授权允许远程访问

    MySQL Community Edition(GPL) 在我们使用mysql数据库时,有时我们的程序与数据库不在同一机器上,这时我们需要远程访问数据库.缺省状态下,mysql的用户是没有远程访问的权 ...

  6. scala学习5--函数二

    to  def test() : Unit = { // for(i <- 1.to(100)){ // println(i) // } for(i <- 1 to 100 ){ prin ...

  7. CSS Sprites的原理(图片整合技术)(CSS精灵)/雪碧图

    CSS Sprites的原理(图片整合技术)(CSS精灵)/雪碧图   一.将导航背景图片,按钮背景图片等有规则的合并成一张背景图,即将多张图片合为一张整图,然后用background-positio ...

  8. vue 子父组件之间的通信,及在调用组件的地方

    这里是用了 element ui 你们也可以看一下管方的文档 http://element.eleme.io/#/zh-CN/component/installation 组件html <div ...

  9. Java学习(运算符,引用数据类型)

    一.  运   算    符 1.算数运算符 运算符是用来计算数据的符号.数据可以是常量,也可以是变量.被运算符操作的数我们称为操作数. 算术运算符最常见的操作就是将操作数参与数学计算,具体使用看下图 ...

  10. 【PAT】1003. 我要通过!(20)

    1003. 我要通过!(20) “答案正确”是自动判题系统给出的最令人欢喜的回复.本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”. ...