http://hihocoder.com/problemset/problem/1466

建出A串和B串的两个后缀自动机

对后缀自动机的每个状态求出sg值。

求出B串的\(sum(x)\),表示B有多少子串的sg值等于x(用拓扑序求)。

对A串的每个状态,求出B串有多少子串的sg值不等于这个状态的sg值,再按拓扑序递推一下。

接下来就类似SPOJ 7258这道题了

从A串开始走,按字典序从小到大,定住A串后,根据在A串停住的状态的sg值再在B串上按拓扑序递推一次求出当前状态往后可以走出多少不等于这个sg值的子串,再在B串上按字典序从小到大走定住B串。

注意空串也算子串。

时间复杂度\(O(n\log n)\),只有求sg函数排序是\(O(n\log n)\)的,其他操作都是\(O(n)\)的。

调了好几天,很恶心啊,把c[nn + 1] = -1;打成c[nn + 1] == -1;了。



要是开-Wall就没这种事了qwq

在周赛结束前10分钟才发现错误,然后改过来A了233

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100003; int tot = 0, cnt, cnt2;
struct State {
State *par, *go[26];
int val, sg; ll f;
} pool[N << 2], *id[N << 1], *tp[N << 1], *tp2[N << 1], *root_A, *root_B, *root, *last, *tmp; State *newState(int num) {
pool[++tot].val = num;
pool[tot].par = 0;
pool[tot].sg = 0;
pool[tot].f = 0;
memset(pool[tot].go, 0, sizeof(pool[tot].go));
return id[++cnt] = &pool[tot];
} void extend(int w) {
State *p = last;
State *np = newState(p->val + 1);
while (p && p->go[w] == 0)
p->go[w] = np, p = p->par;
if (p == 0) np->par = root;
else {
State *q = p->go[w];
if (q->val == p->val + 1) np->par = q;
else {
State *nq = newState(p->val + 1);
memcpy(nq->go, q->go, sizeof(nq->go));
nq->par = q->par;
q->par = np->par = nq;
while (p && p->go[w] == q)
p->go[w] = nq, p = p->par;
}
}
last = np;
} char Sa[N], Sb[N], ansa[N], ansb[N];
int nn, c[N << 1], ansalen = 0, ansblen = 0;
ll sum[N], k; void pre(int len) {
cnt2 = cnt;
for (int i = 1; i <= cnt; ++i) ++c[id[i]->val];
for (int i = 1; i <= len; ++i) c[i] += c[i - 1];
for (int i = cnt; i >= 1; --i) tp[c[id[i]->val]--] = id[i]; for (int i = cnt; i >= 1; --i) {
tp2[i] = tmp = tp[i]; nn = 0;
for (int w = 0; w < 26; ++w)
if (tmp->go[w]) {
tmp->f += tmp->go[w]->f;
c[++nn] = tmp->go[w]->sg;
}
++tmp->f; stable_sort(c + 1, c + nn + 1);
if (c[1] != 0 || nn == 0) tmp->sg = 0;
else {
c[nn + 1] = -1;
for (int j = 1; j <= nn; ++j)
if (c[j] != c[j + 1] && c[j] + 1 != c[j + 1]) {
tmp->sg = c[j] + 1;
break;
}
}
}
} void pre2(int len) {
memset(c, 0, sizeof(int) * (len + 1));
for (int i = 1; i <= cnt; ++i) ++c[id[i]->val];
for (int i = 1; i <= len; ++i) c[i] += c[i - 1];
for (int i = cnt; i >= 1; --i) tp[c[id[i]->val]--] = id[i]; for (int i = cnt; i >= 1; --i) {
tmp = tp[i];
nn = 0;
for (int w = 0; w < 26; ++w)
if (tmp->go[w]) {
tmp->f += tmp->go[w]->f;
c[++nn] = tmp->go[w]->sg;
} stable_sort(c + 1, c + nn + 1);
if (c[1] != 0 || nn == 0) tmp->sg = 0;
else {
c[nn + 1] = -1;
for (int j = 1; j <= nn; ++j)
if (c[j] != c[j + 1] && c[j] + 1 != c[j + 1]) {
tmp->sg = c[j] + 1;
break;
}
} tmp->f += sum[tmp->sg];
}
} void work_B(int nu) {
for (int i = cnt2; i >= 1; --i) {
tmp = tp2[i]; tmp->f = 0;
for (int w = 0; w < 26; ++w)
if (tmp->go[w])
tmp->f += tmp->go[w]->f;
if (tmp->sg != nu) ++tmp->f;
} tmp = root_B;
bool flag;
while (k) {
flag = false;
if (tmp->sg != nu) --k;
if (k == 0) {flag = true; break;}
for (int w = 0; w < 26; ++w)
if (tmp->go[w] && k)
if (tmp->go[w]->f >= k) {
flag = true;
tmp = tmp->go[w];
ansb[++ansblen] = 'a' + w;
break;
} else
k -= tmp->go[w]->f;
if (!flag) break;
} if (!flag) puts("NO");
else {
for (int i = 1; i <= ansalen; ++i) putchar(ansa[i]); puts("");
for (int i = 1; i <= ansblen; ++i) putchar(ansb[i]); puts("");
}
} int main() {
scanf("%lld%s%s", &k, Sa + 1, Sb + 1);
int lena = strlen(Sa + 1), lenb = strlen(Sb + 1); cnt = 0;
root_B = root = last = newState(0);
for (int i = 1; i <= lenb; ++i)
extend(Sb[i] - 'a');
pre(lenb);
for (int i = 1; i <= cnt; ++i)
if (tp[i] != root_B) sum[tp[i]->sg] += tp[i]->val - tp[i]->par->val;
else ++sum[tp[i]->sg];
for (int i = 0; i <= lena; ++i)
sum[i] = root_B->f - sum[i]; cnt = 0;
root_A = root = last = newState(0);
for (int i = 1; i <= lena; ++i)
extend(Sa[i] - 'a');
pre2(lena); tmp = root_A;
bool flag;
while (k) {
flag = false;
if (sum[tmp->sg] >= k) {
work_B(tmp->sg);
return 0;
}
k -= sum[tmp->sg];
for (int w = 0; w < 26; ++w)
if (tmp->go[w] && k)
if (tmp->go[w]->f >= k) {
flag = true;
ansa[++ansalen] = 'a' + w;
tmp = tmp->go[w];
break;
} else
k -= tmp->go[w]->f;
if (!flag) break;
} puts("NO");
return 0;
}

【hihoCoder 1466】后缀自动机六·重复旋律9的更多相关文章

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

    思路 后缀数组+博弈论的好题,首先对两个串都建出SAM,然后题目的要求实际上就是在SAM的trans上转移即可 DAG的博弈是经典问题,然后dfs求出SG函数,两个游戏的组合就是把SG函数异或起来,异 ...

  2. hihoCoder #1445 : 后缀自动机二·重复旋律5

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

  3. hihoCoder #1465 : 后缀自动机五·重复旋律8

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

  4. hihocoder 1457 后缀自动机四·重复旋律7 求不同子串的和

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

  5. HIHOcoder 1457 后缀自动机四·重复旋律7

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

  6. hihocoder 1457 后缀自动机四·重复旋律7 ( 多串连接处理技巧 )

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

  7. hihoCoder #1457 : 后缀自动机四·重复旋律7(后缀自动机 + 拓扑排序)

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

  8. hihoCoder.1465.后缀自动机五 重复旋律8(后缀自动机)

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

  9. HIHOcoder 1449 后缀自动机三·重复旋律6

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

随机推荐

  1. 10.26最后的模拟DAY2 数字对[暴力]

    数字对 [题目描述] 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= ...

  2. 2013.2.A&&3.A

    半期考之后,磨磨蹭蹭的刷了两套长乐的模拟题[=-=我现在实在是不敢恭维自己的刷题速度]感觉貌似很久没有来这里喂食了,就顺便yy下题解好了 2013.2.A: ice :BFS和spfa都可以,我打了个 ...

  3. Code First 启用迁移时出错 HRESULT:0x80131040

    问题:Enable-Migrations 使用“8”个参数调用“CreateInstanceFrom”时发生异常 (异常来自 HRESULT:0x80131040) PM> Enable-Mig ...

  4. [原]OS X 10.9 Mavericks - Virtual Serial Port Issues

    If want to do iOS kernel debugging on A4 device, first you should install Virtual COM port (VCP) dri ...

  5. c语言:将二进制数按位输出

    问题: 1.输入int 20,其二进制为10100,按位输出10100; 2.或者将1转化为“+”,0转化为“-”,输出就是” + - + - - “; int biTofh(int bi,int l ...

  6. hdu2837数论

    http://acm.hdu.edu.cn/showproblem.php?pid=2837 // a^b%p=a^(b%phi(p)+phi(p))%p #include<iostream&g ...

  7. 淘宝ued - 前端智勇大闯关(第三季)答案(更新)

    淘宝ued - 前端智勇大闯关(第三季)答案(更新) 下午在微博上看到了淘宝智勇大闯关第三季的信息,感觉挺有意思的,于是就尝试做了下.附上题目地址: http://ued.campus.alibaba ...

  8. Newlife商业源码分享

    [商业源码]生日大放送-Newlife商业源码分享 今天是农历六月二十三,是@大石头的生日,记得每年生日都会有很劲爆的重量级源码送出,今天Newlife群和论坛又一次疯狂了,吃水不忘挖井人,好的东西肯 ...

  9. squid和varnish的小结

    squid和varnish的小结 http://blog.haohtml.com/     上周初步接触linux下的这2个反向缓存软件,都实验了一下,貌似squid还是比较顺利的,varnish则碰 ...

  10. asp.net中的路由系统

    ASP.NET MVC重写了ASP.NET管道HttpModule和处理程序HttpHandler.MVC自定义了MvcHandler实现了Controller的激活和Action的执行.但是在请求到 ...