标签:mon resion space main 字符串 效率 sample else lan
Background:
The SMS in Byterland mobile service are charging in dollars-per-byte. That is why the little cat is worrying about how long could the longest original text be.yeshowmuchiloveyoumydearmotherreallyicannotbelieveit yeaphowmuchiloveyoumydearmother
27
求两个字符串的最长的公共字串。
后缀自动机:可以直接匹配,然后又默写了一遍后缀自动机。
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn=3000000; char chr[maxn],str[maxn]; struct SAM { int ch[maxn][26],fa[maxn],maxlen[maxn],Last,sz; void init() { sz=Last=1; fa[1]=maxlen[1]=0; memset(ch[1],0,sizeof(ch[1])); } void add(int x) { int np=++sz,p=Last;Last=np; memset(ch[np],0,sizeof(ch[np])); maxlen[np]=maxlen[p]+1; while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p]; if(!p) fa[np]=1; else { int q=ch[p][x]; if(maxlen[p]+1==maxlen[q]) fa[np]=q; else { int nq=++sz; memcpy(ch[nq],ch[q],sizeof(ch[q])); maxlen[nq]=maxlen[p]+1; fa[nq]=fa[q]; fa[q]=fa[np]=nq; while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p]; } } } void solve() { scanf("%s",chr); int L=strlen(chr),x,tmp=0,ans=0;Last=1; for(int i=0;i<L;i++){ x=chr[i]-‘a‘; if(ch[Last][x]) tmp++,Last=ch[Last][x]; else { while(Last&&!ch[Last][x]) Last=fa[Last]; if(!Last) tmp=0,Last=1; else tmp=maxlen[Last]+1,Last=ch[Last][x]; } ans=max(ans,tmp); } printf("%d\n",ans); } }; SAM Sam; int main() { int T,i,L; while(~scanf("%s",chr)){ Sam.init(); L=strlen(chr); for(i=0;i<L;i++) Sam.add(chr[i]-‘a‘); Sam.solve(); } return 0; }
后缀数组:需要把两个串连接起来,之间加一个特殊符号,用来保证得到的结果符合两个串来自不同的母串。
后缀自动机94ms,后缀数组782ms。这种基本题型我还是愿意写后缀自动机,不过练一练总是有好处的。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=4100000; char str1[maxn],str2[maxn]; int L,ch[maxn]; struct SA { int cntA[maxn],cntB[maxn],A[maxn],B[maxn]; int rank[maxn],sa[maxn],tsa[maxn],ht[maxn]; void sort() { for (int i = 0; i < 28; i ++) cntA[i] = 0; for (int i = 1; i <= L; i ++) cntA[ch[i]] ++; for (int i = 1; i < 28; i ++) cntA[i] += cntA[i - 1]; for (int i = L; i; i --) sa[cntA[ch[i]] --] = i; rank[sa[1]] = 1; for (int i = 2; i <= L; i ++){ rank[sa[i]] = rank[sa[i - 1]]; if (ch[sa[i]] != ch[sa[i - 1]]) rank[sa[i]] ++; } for (int l = 1; rank[sa[L]] < L; l <<= 1){ for (int i = 0; i <= L; i ++) cntA[i] = 0; for (int i = 0; i <= L; i ++) cntB[i] = 0; for ( int i = 1; i <= L; i ++){ cntA[A[i] = rank[i]] ++; cntB[B[i] = (i + l <= L) ? rank[i + l] : 0] ++; } for (int i = 1; i <= L; i ++) cntB[i] += cntB[i - 1]; for (int i = L; i; i --) tsa[cntB[B[i]] --] = i; for (int i = 1; i <= L; i ++) cntA[i] += cntA[i - 1]; for (int i = L; i; i --) sa[cntA[A[tsa[i]]] --] = tsa[i]; rank[sa[1]] = 1; for (int i = 2; i <= L; i ++){ rank[sa[i]] = rank[sa[i - 1]]; if (A[sa[i]] != A[sa[i - 1]] || B[sa[i]] != B[sa[i - 1]]) rank[sa[i]] ++; } } } void getht() { for (int i = 1, j = 0; i <= L; i ++){ if (j) j --; while (ch[i + j] == ch[sa[rank[i] - 1] + j]) j ++; ht[rank[i]] = j; } } }; SA Sa; int main() { scanf("%s",str1+1); scanf("%s",str2+1); int L1=strlen(str1+1); int L2=strlen(str2+1); for(int i=1;i<=L1;i++) ch[i]=str1[i]-‘a‘+1; ch[L1+1]=27; for(int i=1;i<=L2;i++) ch[i+L1+1]=str2[i]-‘a‘+1; L=L1+L2+1; Sa.sort(); Sa.getht(); int ans=0; for(int i = 1; i <= L; i++) { if((Sa.sa[i]<=L1)!=(Sa.sa[i-1]<=L1)) ans = max(ans, Sa.ht[i]); } printf("%d\n",ans); return 0; }
POJ2774Long Long Message (后缀数组&后缀自动机)
标签:mon resion space main 字符串 效率 sample else lan
原文地址:http://www.cnblogs.com/hua-dong/p/8016450.html