SPOJ 1811 LCS,SPOJ 1812 LCS2【SAM裸题,clj的ppt很清楚

来源:互联网 发布:老馆艳后 知乎 编辑:程序博客网 时间:2024/05/14 10:47

反正clj的ppt都讲了

- LCS的话……因为只需要匹配一次,也就不需要更新pre的值了。

- 然而LCS2……因为有多个字符串要匹配,于是要把整个SAM上的rec都更新了,所以多了一步从后往前更新的

至于【rec[pre[k]]=dis[pre[k]]】……是因为……parent树的性质……max[pre[k]]=dis[pre[k]]<min[k],而既然k是可达的,说明pre上子串长度的任意取值都是可达的(原理就是对于某个状态i,i可以表示的串长度肯定比它在parent树上的父节点能表示的最大长度更大……l[i]>r[pre[i]])【woc好难解释啊QAQ,反正就是那个意思】



LCS ↓

#include<bits/stdc++.h>#define MAXN 500057//#define FLAZE_NAIVEusing namespace std;char read_s[MAXN];struct sam{int son[MAXN][26],pre[MAXN],dis[MAXN];int lst,cnt,lth;int p,q,np,nq;void insert(int x){dis[np=++cnt]=dis[p=lst]+1;lst=np;for(;p&&!son[p][x];p=pre[p])son[p][x]=np;if(!p)return pre[np]=1,void();q=son[p][x];if(dis[q]==dis[p]+1)pre[np]=q;else{dis[nq=++cnt]=dis[p]+1;memcpy(son[nq],son[q],sizeof son[q]);pre[nq]=pre[q];pre[q]=pre[np]=nq;for(;p&&son[p][x]==q;p=pre[p])son[p][x]=nq;}}void build(){cnt=lst=1;scanf("%s",read_s);lth=strlen(read_s);for(int i=0;i<lth;++i)insert(read_s[i]-'a');}#ifdef FLAZE_NAIVEchar tmp[MAXN];void dfs(int now,int stp){for(int i=0;i<26;++i)if(son[now][i]){tmp[stp]='a'+i;puts(tmp);dfs(son[now][i],stp+1);}tmp[stp]=' ';}#endifint ans;void check(){ans=0;int now=1,tmp=0;scanf("%s",read_s);int str_len=strlen(read_s);for(int i=0;i<str_len;++i){int x=read_s[i]-'a';if(son[now][x])++tmp,now=son[now][x];else{for(;now&&!son[now][x];now=pre[now]);if(!now)now=1,tmp=0;elsetmp=dis[now]+1,now=son[now][x];}ans=max(ans,tmp);}}}SAM_s;int main(){SAM_s.build();//SAM_s.dfs(1,0);SAM_s.check();printf("%d",SAM_s.ans);return 0;}

LCS2 ↓

#include<bits/stdc++.h>#define MAXN 200057#define INF 0x3f3f3f3f//#define FLAZE_NAIVEusing namespace std;char read_s[MAXN>>1];struct t1{int son[MAXN][26],pre[MAXN],dis[MAXN];int cnt,lst;int lth;int p,np,q,nq;void insert(int x){dis[np=++cnt]=dis[p=lst]+1;lst=np;for(;p&&!son[p][x];p=pre[p])son[p][x]=np;if(!p)return pre[np]=1,void();q=son[p][x];if(dis[q]==dis[p]+1)pre[np]=q;else{dis[nq=++cnt]=dis[p]+1;memcpy(son[nq],son[q],sizeof son[q] );pre[nq]=pre[q];pre[q]=pre[np]=nq;for(;p&&son[p][x]==q;p=pre[p])son[p][x]=nq;}}void build(){lst=cnt=1;scanf("%s",read_s);lth=strlen(read_s);for(int i=0;i<lth;++i)insert(read_s[i]-'a');}#ifdef FLAZE_NAIVEchar tmp[MAXN>>1];void dfs(int now,int stp){for(int i=0;i<26;++i)if(son[now][i]){tmp[stp]=97+i;puts(tmp);dfs(son[now][i],stp+1);}tmp[stp]=' ';}#endifint s[MAXN],v[MAXN];void sort(){for(int i=1;i<=cnt;++i)++v[dis[i]];for(int i=1;i<=lth;++i)v[i]+=v[i-1];for(int i=1;i<=cnt;++i)s[v[dis[i]]--]=i;} int ans;int rec[MAXN];int pre_rec[MAXN];void check(){memset(rec,0,sizeof rec);int tmp=0,now=1;int l2=strlen(read_s);for(int i=0;i<l2;++i){int x=read_s[i]-'a';if(son[now][x])now=son[now][x],++tmp;else{for(;now&&!son[now][x];now=pre[now]);if(!now)now=1,tmp=0;else{tmp=dis[now]+1;now=son[now][x];}}rec[now]=max(rec[now],tmp);}for(int i=cnt;i;--i){int k=s[i];pre_rec[k]=min(pre_rec[k],rec[k]);if(rec[k]&&pre[k])rec[pre[k]]=dis[pre[k]];}}}SAM_s;int main(){SAM_s.build();//SAM_s.dfs(1,0);SAM_s.sort();memset(SAM_s.pre_rec,INF,sizeof SAM_s.pre_rec);while(~scanf("%s",read_s))SAM_s.check();for(int i=1;i<=SAM_s.cnt;++i)SAM_s.ans=max(SAM_s.ans,SAM_s.pre_rec[i]);printf("%d",SAM_s.ans);return 0;}



0 0
原创粉丝点击