[POI2000]Repetitions
题目大意:
求多个字符串的LCS。
思路:
同SPOJ-LCS2,不过因为SPOJ上数据比较水,当时用错误的写法过掉了,这次用正确的写法重新过了一遍。
拓扑排序按照每个状态的len值,用计数排序实现。
每个状态往上更新时,应该对std::min(s[p].maxlen,s[q].len)取max(每个状态能匹配的最长子串长度不超过len)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int inf=0x7fffffff; 5 const int LEN=2001; 6 int n; 7 char s[LEN]; 8 class SuffixAutomaton { 9 private: 10 static const int SIGMA_SIZE=26; 11 struct State { 12 int len,link,go[SIGMA_SIZE],maxlen,min; 13 }; 14 int sz,root,last,len; 15 int cnt[LEN],top[LEN<<1]; 16 State s[LEN<<1]; 17 int newState(const int l) { 18 sz++; 19 s[sz].len=l; 20 s[sz].min=inf; 21 return sz; 22 } 23 int idx(const char ch) { 24 return ch-'a'; 25 } 26 void extend(const char ch) { 27 int w=idx(ch); 28 int p=last; 29 int new_p=newState(s[p].len+1); 30 while(p&&!s[p].go[w]) { 31 s[p].go[w]=new_p; 32 p=s[p].link; 33 } 34 if(!p) { 35 s[new_p].link=root; 36 s[root].go[w]=new_p; 37 } else { 38 int q=s[p].go[w]; 39 if(s[q].len==s[p].len+1) { 40 s[new_p].link=q; 41 } else { 42 int new_q=newState(s[p].len+1); 43 memcpy(s[new_q].go,s[q].go,sizeof s[q].go); 44 s[new_q].link=s[q].link; 45 s[q].link=s[new_p].link=new_q; 46 while(p&&s[p].go[w]==q) { 47 s[p].go[w]=new_q; 48 p=s[p].link; 49 } 50 } 51 } 52 last=new_p; 53 } 54 public: 55 void build(char str[]) { 56 root=last=newState(0); 57 len=strlen(str); 58 for(int i=0;str[i];i++) extend(str[i]); 59 } 60 void top_sort() { 61 for(int i=1;i<=sz;i++) cnt[s[i].len]++; 62 for(int i=len;i;i--) cnt[i-1]+=cnt[i]; 63 for(int i=1;i<=sz;i++) top[cnt[s[i].len]--]=i; 64 } 65 void match(char str[]) { 66 int p=root,tmp=0; 67 for(int i=0;str[i];i++) { 68 int w=idx(str[i]); 69 if(s[p].go[w]) { 70 tmp++; 71 p=s[p].go[w]; 72 } else { 73 while(p&&!s[p].go[w]) { 74 p=s[p].link; 75 } 76 if(!p) { 77 tmp=0; 78 p=root; 79 } else { 80 tmp=s[p].len+1; 81 p=s[p].go[w]; 82 } 83 } 84 s[p].maxlen=std::max(s[p].maxlen,tmp); 85 } 86 for(int i=1;i<=sz;i++) { 87 int p=top[i],q=s[p].link; 88 s[q].maxlen=std::max(s[q].maxlen,std::min(s[p].maxlen,s[q].len)); 89 s[p].min=std::min(s[p].min,s[p].maxlen); 90 s[p].maxlen=0; 91 } 92 } 93 int lcs() { 94 int ret=0; 95 for(int i=1;i<=sz;i++) ret=std::max(ret,s[i].min); 96 return ret; 97 } 98 }; 99 SuffixAutomaton sam; 100 int main() { 101 scanf("%d",&n); 102 scanf("%s",s); 103 sam.build(s); 104 sam.top_sort(); 105 for(int i=2;i<=n;i++) { 106 scanf("%s",s); 107 sam.match(s); 108 } 109 printf("%d\n",sam.lcs()); 110 return 0; 111 }