【hihoCoder 1466】后缀自动机六·重复旋律9
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的更多相关文章
- HIHOcoder 1466 后缀自动机六·重复旋律9
思路 后缀数组+博弈论的好题,首先对两个串都建出SAM,然后题目的要求实际上就是在SAM的trans上转移即可 DAG的博弈是经典问题,然后dfs求出SG函数,两个游戏的组合就是把SG函数异或起来,异 ...
- hihoCoder #1445 : 后缀自动机二·重复旋律5
#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...
- 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的大小可以拓扑排序求出 ...
随机推荐
- 10.26最后的模拟DAY2 数字对[暴力]
数字对 [题目描述] 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= ...
- 2013.2.A&&3.A
半期考之后,磨磨蹭蹭的刷了两套长乐的模拟题[=-=我现在实在是不敢恭维自己的刷题速度]感觉貌似很久没有来这里喂食了,就顺便yy下题解好了 2013.2.A: ice :BFS和spfa都可以,我打了个 ...
- Code First 启用迁移时出错 HRESULT:0x80131040
问题:Enable-Migrations 使用“8”个参数调用“CreateInstanceFrom”时发生异常 (异常来自 HRESULT:0x80131040) PM> Enable-Mig ...
- [原]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 ...
- c语言:将二进制数按位输出
问题: 1.输入int 20,其二进制为10100,按位输出10100; 2.或者将1转化为“+”,0转化为“-”,输出就是” + - + - - “; int biTofh(int bi,int l ...
- hdu2837数论
http://acm.hdu.edu.cn/showproblem.php?pid=2837 // a^b%p=a^(b%phi(p)+phi(p))%p #include<iostream&g ...
- 淘宝ued - 前端智勇大闯关(第三季)答案(更新)
淘宝ued - 前端智勇大闯关(第三季)答案(更新) 下午在微博上看到了淘宝智勇大闯关第三季的信息,感觉挺有意思的,于是就尝试做了下.附上题目地址: http://ued.campus.alibaba ...
- Newlife商业源码分享
[商业源码]生日大放送-Newlife商业源码分享 今天是农历六月二十三,是@大石头的生日,记得每年生日都会有很劲爆的重量级源码送出,今天Newlife群和论坛又一次疯狂了,吃水不忘挖井人,好的东西肯 ...
- squid和varnish的小结
squid和varnish的小结 http://blog.haohtml.com/ 上周初步接触linux下的这2个反向缓存软件,都实验了一下,貌似squid还是比较顺利的,varnish则碰 ...
- asp.net中的路由系统
ASP.NET MVC重写了ASP.NET管道HttpModule和处理程序HttpHandler.MVC自定义了MvcHandler实现了Controller的激活和Action的执行.但是在请求到 ...