OJ3446copy
Posted farway17
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OJ3446copy相关的知识,希望对你有一定的参考价值。
题意:
给你 (n) 个字符串,选每个字符串的一个子串依次拼在一起形成一个字符串 (T) 。按字典序输出所有可能的 (T) 并统计方案数。
(输入文件不超过 1 MB ,输出文件不超过 200 MB .)
题解:
对每个字符串都建立一个 SAM 。如果某个节点没有转移边,则连向右边 SAM (最靠左的)根的转移边指向的节点。
输出直接 dfs ,统计方案数直接拓扑序。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
const int N=3000005,M=7000005,Mod=1000000007;
int pre[N],len[N],ch[N][5],lst,cnt,rt[N],size[N];
int n,m[233],get[N],head[N],nxt[M],to[M],tot,in[N],pl[N],q[N];
char ans[N],h[5];
string s[N];
void extend(int r, int c)
{
int p=lst,np=++cnt;lst=np;
len[np]=len[p]+1,size[np]=1;
for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;
if(!p) {
pre[np]=r;
return ;
}
int q=ch[p][c];
if(len[p]+1==len[q]) {
pre[np]=q;
return ;
}
int nq=++cnt;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
pre[nq]=pre[q],pre[q]=pre[np]=nq;
for(;ch[p][c]==q;p=pre[p])ch[p][c]=nq;
}
void addedge(int u, int v) {
++in[v],nxt[++tot]=head[u];head[u]=tot,to[tot]=v;
}
void dfs(int u, int v)
{
puts(ans);
for(int i=1;i<=4;++i)
if(ch[u][i])
{
ans[v]=h[i];
dfs(ch[u][i],v+1);
ans[v]='