HIHOcoder 1466 后缀自动机六·重复旋律9
思路
后缀数组+博弈论的好题,首先对两个串都建出SAM,然后题目的要求实际上就是在SAM的trans上转移即可
DAG的博弈是经典问题,然后dfs求出SG函数,两个游戏的组合就是把SG函数异或起来,异或是0就是先手必败,不是0就是先手必胜
然后要求先手必胜,所以就是求异或不为0
接下来递推的求出第k大的串即可,类似于树上的第k大的思路
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int MAXN = 100100*2;
struct SAM{
int trans[MAXN][26],suflink[MAXN],maxlen[MAXN],sg[MAXN],cnt;
long long cnt_sg[MAXN][28];
int new_state(int _maxlen,int *_trans,int _suflink){
++cnt;
maxlen[cnt]=_maxlen;
if(_trans)
for(int i=0;i<26;i++)
trans[cnt][i]=_trans[i];
suflink[cnt]=_suflink;
return cnt;
}
int add_len(int u,int c){
int z=new_state(maxlen[u]+1,NULL,0);
while(u&&(!trans[u][c])){
trans[u][c]=z;
u=suflink[u];
}
if(!u){
suflink[z]=1;
return z;
}
int v=trans[u][c];
if(maxlen[v]==maxlen[u]+1){
suflink[z]=v;
return z;
}
int y=new_state(maxlen[u]+1,trans[v],suflink[v]);
suflink[z]=suflink[v]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return z;
}
int cal_sg(int u){
if(sg[u]!=-1)
return sg[u];
bool mid[30]={0};
for(int i=0;i<26;i++){
if(!trans[u][i])
continue;
int t=cal_sg(trans[u][i]);
mid[t]=true;
for(int j=0;j<27;j++)
cnt_sg[u][j]+=cnt_sg[trans[u][i]][j];
}
for(int i=0;i<30;i++)
if(!mid[i]){
sg[u]=i;
break;
}
cnt_sg[u][sg[u]]++;
for(int i=0;i<27;i++)
cnt_sg[u][27]+=cnt_sg[u][i];
return sg[u];
}
void init(char *s,int len){
int pre=1;
cnt=1;
for(int i=1;i<=len;i++)
pre=add_len(pre,s[i]-'a');
memset(sg,-1,sizeof(sg));
cal_sg(1);
}
}A,B;
int lena,lenb,mida;
long long k;
char sa[MAXN],sb[MAXN],ax[MAXN],bx[MAXN];
long long calc_mid(int Ax,int Bx){
long long ans=0;
for(int i=0;i<27;i++)
ans+=A.cnt_sg[Ax][i]*(B.cnt_sg[Bx][27]-B.cnt_sg[Bx][i]);
return ans;
}
int dfsA(int pos,int x){
int mid1=B.cnt_sg[1][27]-B.cnt_sg[1][A.sg[x]];
if(mid1>=k)
return x;
else
k-=mid1;
for(int i=0;i<26;i++){
if(!A.trans[x][i])
continue;
int mid2=calc_mid(A.trans[x][i],1);
if(mid2<k)
k-=mid2;
else{
ax[pos]='a'+i;
return dfsA(pos+1,A.trans[x][i]);
}
}
return -1;
}
int dfsB(int pos,int x){
k-=B.sg[x]!=A.sg[mida];
if(k==0)
return x;
for(int i=0;i<26;i++){
if(!B.trans[x][i])
continue;
int mid2=B.cnt_sg[B.trans[x][i]][27]-B.cnt_sg[B.trans[x][i]][A.sg[mida]];
if(mid2<k)
k-=mid2;
else{
bx[pos]='a'+i;
return dfsB(pos+1,B.trans[x][i]);
}
}
return -1;
}
signed main(){
scanf("%lld",&k);
scanf("%s",sa+1);
lena=strlen(sa+1);
scanf("%s",sb+1);
lenb=strlen(sb+1);
A.init(sa,lena);
B.init(sb,lenb);
if((mida=dfsA(1,1))==-1){
printf("NO\n");
return 0;
}
dfsB(1,1);
printf("%s\n",ax+1);
printf("%s\n",bx+1);
return 0;
}
HIHOcoder 1466 后缀自动机六·重复旋律9的更多相关文章
- hihoCoder #1445 : 后缀自动机二·重复旋律5
#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...
- 【hihoCoder 1466】后缀自动机六·重复旋律9
http://hihocoder.com/problemset/problem/1466 建出A串和B串的两个后缀自动机 对后缀自动机的每个状态求出sg值. 求出B串的\(sum(x)\),表示B有多 ...
- hihoCoder #1465 : 后缀自动机五·重复旋律8
http://hihocoder.com/problemset/problem/1465 求S的循环同构串在T中的出现次数 将串S变成SS 枚举SS的每个位置i,求出以i结尾的SS的子串 与 T的最长 ...
- hihocoder 1457 后缀自动机四·重复旋律7 求不同子串的和
描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的是小Hi发现了一部名字叫<十进制进行曲大全>的作品集,顾名思义,这部作品集里有许多作品 ...
- HIHOcoder 1457 后缀自动机四·重复旋律7
思路 后缀自动机题目,题目本质上是要求求出所有不同的子串的和,SAM每个节点中存放的子串互不相同,所以对于每个节点的sum,可以发现是可以递推的,每个点对子节点贡献是sum[x]*10+c*sz[x] ...
- hihocoder 1457 后缀自动机四·重复旋律7 ( 多串连接处理技巧 )
题目链接 分析 : 这道题对于单个串的用 SAM 然后想想怎么维护就行了 但是多个串下.可以先将所有的串用一个不在字符集( 这道题的字符集是 '0' ~ '9' ) 链接起来.建立后缀自动机之后 在统 ...
- hihoCoder #1457 : 后缀自动机四·重复旋律7(后缀自动机 + 拓扑排序)
http://hihocoder.com/problemset/problem/1457 val[i] 表示状态i所表示的所有字符串的十进制之和 ans= ∑ val[i]在后缀自动机上,从起始状态走 ...
- hihoCoder.1465.后缀自动机五 重复旋律8(后缀自动机)
题目链接 \(Description\) 给定母串S,求模式串的循环同构串在S中的出现次数. \(Solution\) 将模式串s复制一遍,在母串的SAM上匹配,记录以每个位置作为后缀所能匹配的最大长 ...
- HIHOcoder 1449 后缀自动机三·重复旋律6
思路 显然endpos的大小就对应了对应子串的出现次数,所以快速求出endpos的大小,然后用它更新对应子串长度(minlen[i]~maxlen[i])的答案即可 endpos的大小可以拓扑排序求出 ...
随机推荐
- ASP.NET MVC Action返回结果类型【转】
ASP.NET MVC 目前一共提供了以下几种Action返回结果类型: 1.ActionResult(base) 2.ContentResult 3.EmptyResult 4.HttpUnauth ...
- uvalive 3887 Slim Span
题意: 一棵生成树的苗条度被定义为最长边与最小边的差. 给出一个图,求其中生成树的最小苗条度. 思路: 最开始想用二分,始终想不到二分终止的条件,所以尝试暴力枚举最小边的长度,然后就AC了. 粗略估计 ...
- 【Hadoop学习之四】HDFS HA搭建(QJM)
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 由于NameNode对于整个HDF ...
- linux 远程执行命令
命令: ssh 命令参数: -l 指定登入用户 -p 设置端口号 -f 后台运行,并推荐加上 -n 参数 -n 将标准输入重定向到 /dev/null,防止读取标准输入 -N 不执行远程命令,只做端口 ...
- django中orm的批量操作
ORM批量操作 数据模型定义 from django.db import models class Product(models.Model): name = models.CharField(max ...
- EasyUi通过POI 实现导出xls表格功能
Spring +EasyUi+Spring Jpa(持久层) EasyUi通过POI 实现导出xls表格功能 EasyUi界面: 点击导出按钮实现数据导入到xls表格中 第一步:修改按钮事件: @Co ...
- Spark With Mongodb 实现方法及error code -5, 6, 13127解决方案
1.spark mongo 读取 val rdd = MongoSpark.builder().sparkSession(spark).pipeline(Seq(`match`(regex(" ...
- WEB前端移动开发初始化
meta篇 1.视窗宽度 <meta name="viewport" content="width=device-width,initial-scale=1.0,m ...
- POJ 3662 Telephone Lines (二分 + 最短路)
Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncoop ...
- flask框架----flask中的wtforms使用
一.简单介绍flask中的wtforms WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证. 安装: pip3 install wtforms 二.简单使用wtfo ...