HIHOcoder 1466 后缀自动机六·重复旋律9

时间:2022-09-06 08:16:06

思路

后缀数组+博弈论的好题,首先对两个串都建出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的更多相关文章

  1. hihoCoder &num;1445 &colon; 后缀自动机二&&num;183&semi;重复旋律5

    #1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...

  2. 【hihoCoder 1466】后缀自动机六&&num;183&semi;重复旋律9

    http://hihocoder.com/problemset/problem/1466 建出A串和B串的两个后缀自动机 对后缀自动机的每个状态求出sg值. 求出B串的\(sum(x)\),表示B有多 ...

  3. hihoCoder &num;1465 &colon; 后缀自动机五&&num;183&semi;重复旋律8

    http://hihocoder.com/problemset/problem/1465 求S的循环同构串在T中的出现次数 将串S变成SS 枚举SS的每个位置i,求出以i结尾的SS的子串 与 T的最长 ...

  4. hihocoder 1457 后缀自动机四&&num;183&semi;重复旋律7 求不同子串的和

    描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的是小Hi发现了一部名字叫<十进制进行曲大全>的作品集,顾名思义,这部作品集里有许多作品 ...

  5. HIHOcoder 1457 后缀自动机四&&num;183&semi;重复旋律7

    思路 后缀自动机题目,题目本质上是要求求出所有不同的子串的和,SAM每个节点中存放的子串互不相同,所以对于每个节点的sum,可以发现是可以递推的,每个点对子节点贡献是sum[x]*10+c*sz[x] ...

  6. hihocoder 1457 后缀自动机四&&num;183&semi;重复旋律7 &lpar; 多串连接处理技巧 &rpar;

    题目链接 分析 : 这道题对于单个串的用 SAM 然后想想怎么维护就行了 但是多个串下.可以先将所有的串用一个不在字符集( 这道题的字符集是 '0' ~ '9' ) 链接起来.建立后缀自动机之后 在统 ...

  7. hihoCoder &num;1457 &colon; 后缀自动机四&&num;183&semi;重复旋律7(后缀自动机 &plus; 拓扑排序&rpar;

    http://hihocoder.com/problemset/problem/1457 val[i] 表示状态i所表示的所有字符串的十进制之和 ans= ∑ val[i]在后缀自动机上,从起始状态走 ...

  8. hihoCoder&period;1465&period;后缀自动机五 重复旋律8&lpar;后缀自动机&rpar;

    题目链接 \(Description\) 给定母串S,求模式串的循环同构串在S中的出现次数. \(Solution\) 将模式串s复制一遍,在母串的SAM上匹配,记录以每个位置作为后缀所能匹配的最大长 ...

  9. HIHOcoder 1449 后缀自动机三&&num;183&semi;重复旋律6

    思路 显然endpos的大小就对应了对应子串的出现次数,所以快速求出endpos的大小,然后用它更新对应子串长度(minlen[i]~maxlen[i])的答案即可 endpos的大小可以拓扑排序求出 ...

随机推荐

  1. &period;net 中 ref out params的区别

    C#中有三个关键字-ref,out ,params,虽然本人不喜欢这三个关键字,因为它们疑似破坏面向对象特性.但是既然m$把融入在c#体系中,那么我们就来认识一下参数修饰符ref,out ,param ...

  2. DoTween学习笔记&lpar;一&rpar;

    DOTween是一个快速,高效,完全统一的类型安全的对象属性动画引擎,免费开源,大量的高级特性. DoTween兼容Unity4.5以上的版本,支持的平台: Win, Mac, Unity WebPl ...

  3. Oracle EBS-SQL &lpar;SYS-11&rpar;&colon;查询系统已打的PATCH&period;sql

    select a.patch_name,         b.DRIVER_FILE_NAME,         c.language,         b.creation_datefrom app ...

  4. 【PHP】震惊,一张图详解递归函数!!!!

    在PHP学习中,递归函数是一个非常重要也是非常难以理解的部分,本博文将通过一张图尽可能演示这个过程,不对之处还请指出

  5. Ext viewport的渲染

    Ext viewport的渲染 1.在app.js里创建 Ext.application({ name: 'MySecurity', extend: 'MySecurity.Application', ...

  6. 个人的MySql配置总结

    lower_case_table_names参数是用来设置MySQL是否让Schema和数据表大小写敏感,我测试的是在查询界面和MySQL控制台界面无法改变它的值,要在配置文件中改变(先关闭服务),一 ...

  7. org&period;apache&period;commons&period;lang&period;exception&period;NestableRuntimeException

    jar包不全 附上一个好的的博客链接→

  8. VB&period;NET 定义多行文本字符的几种方式

    vbCrLf 在 .NET 刚刚推出的时候,VB作为一款被微软用来"衬托"C#的语言,在许多细节设计上远不如C#方便. 比如在C#中写一个多行文本,就有各种方式: string s ...

  9. 关于构造函数和this调用的思考

    文中一系列思考和内容引发自以下问题:我需要在一个类的构造函数中调用另一个对象的构造函数,并使用this初始化其中的一个引用成员. 主要遇到的问题: 1. 构造函数的初始化列表中能访问this吗? 很明 ...

  10. C&num; POST数据base64到接口会出错的问题

    这个base64在requestHeader里面变成了base64=hySGNg22yX0AIjNQvNJw0xHEbi32NH%2BiRVKDkbOmUiKpxW0%2FS6rUgfLmSa527Y ...