SAP_AC自动机_后缀数组模版集合

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

网络流增广路25行SAP算法KMR风格代码

int now[N];//点的当前弧

int pre[N];//点的前驱

int d[N];//点的标号

int num[N];//标号为i的个数

int his[N];//历史流量

int top[N],c[M],prev[M],end[M];//邻接表

主程序

Int Shortest_Augment_Path(){

int i=s,j,k,flow=MaxLongint,ret=0;

for(int i=1;i<=n;++i)now[i]=top[i];num[0]=n;

while(d[s]!=n){

his[i]=flow;

for(k=now[i];k;k=prev[k])if(c[k]&&d[j=end[k]]+1==d[i])break;找标号点

if(k){

if(c[now[i]=k]

pre[j]=i;i=j;记录前驱

if(i==t){ 找到一条增广路

ret+=flow;

while(i!=s)i=pre[i],c[now[i]]-=flow,c[now[i]^1]+=flow;修改路上的流量

flow=MaxLongint;

}

}else{

if(--num[d[i]]==0)break;d[i]=n;断层优化

for(k=now[i]=top[i];k;k=prev[k])if(c[k]&&d[end[k]]+1

d[i]=d[end[now[i]=k]]+1;

++num[d[i]];

if(i!=s)i=pre[i],flow=his[i];

}

}

return ret;

}

此程序为本人在借鉴了前人代码的基础上经过压行修改后出炉的,代码只有25行,充分照顾了不想多写代码的童鞋。

AC自动机建立17行模版。

Trie 树组,假设只有26个字母。int son[N][26];

转移函数。int f[N][26];

失败指针。int Pi[N];

bfs队列Int que[N];

Trie树的建立

void Insert(char *s)

{

int len=strlen(s),c,now=0;

for(int i=0;i

{

c=s[i]-'a';

if(!son[now][c])son[now][c]=++tot;

now=son[now][c];

}

}

AC自动机的建立。

void Aho_Corasick() 对,这是AC自动机的英文。

{

for(int head=1,tail=1,x,u,k,i;head<=tail;++head) //head头指针,tail尾指针。

{

u=que[head];

for(i=0;i<26;++i)

if(son[u][i])f[u][i]=que[++tail]=son[u][i];

if(!u)continue; //若当前点为root,退出。

for(i=0;i<26;++i)

{

k=Pi[u];

while(k&&!son[k][i])k=Pi[k]; //算出转移函数。

if((x=son[u][i]))Pi[x]=son[k][i];

else f[u][i]=son[k][i];

}

}

}

此AC自动机的代码是我在借鉴前人的基础上做了点改动后写的。标准风格是17行,KMR风格是14行。

后缀数组20行模版

Int c[N]; \\基数排序的数组。

Int rank[N];\\排名数组。

Int tmp[N];\\辅助排名数组。

Int SA[N];\\众所周知的Suffix_Array数组。

Int s[N];\\原字符串。

主程序

void say(int *rank,int *tmp)

{

rep(i,n)c[s[i]-'a']++;//基数排序

for(int i=0;i<26;i++)c[i]+=c[i-1];

rep(i,n)sa[c[s[i]-'a']--]=i;

rep(i,n)rank[sa[i]]=rank[sa[i-1]]+1-(s[sa[i]]==s[sa[i-1]]);

for(int len=1;len

{

memset(c,0,sizeof(c));

rep(i,n)++c[rank[i+len]];//按第二关键字进行第一次基数排序

rep(i,n)c[i]+=c[i-1];

rep(i,n)tmp[c[rank[i+len]]--]=i;

memset(c,0,sizeof(c));

rep(i,n)++c[rank[i]];//按第一关键字进行第二次基数排序

rep(i,n)c[i]+=c[i-1];

down(i,n)sa[c[rank[tmp[i]]]--]=tmp[i];//按第一次排序后的结果处理SA数组

rep(i,n)tmp[sa[i]]=tmp[sa[i-1]]+1-//将排名暂时存在tmp中

(rank[sa[i]]==rank[sa[i-1]]&&rank[sa[i]+len]==rank[sa[i-1]+len]);

swap(rank,tmp);//这里用了指针优化,省去了memcpy。

}

}

相关文档
最新文档