[acm/icpc2016ChinaFinal][CodeforcesGym101194] Mr. Panda and Fantastic Beasts
地址:http://codeforces.com/gym/101194
题目:略
思路:
这题做法挺多的,可以sam也可以后缀数组,我用sam做的。
1.我自己yy的思路(瞎bb的)
把第一个串建立sam,然后让其他串在上面跑。
每走到一个位置p,当前长度为num,就代表这个endpos集合里的长度小于等于num的字符串是被包含了,同时parent树的所有祖先节点也要标记为被包含。
这一步的具体做法是:用一个mi数组表示到达该节p点时的长度大于mi[p]时,才算未被包含(到达长度指的是从root出发经过某条路径到p的长度),所以其他串在sam上走到每个节点p,长度为num时,记录下mi[p]=max(mi[p],num);
再跑完所有串后,来更新parent树上的节点。先拓扑排序,然后如果mi[p]>0,mi[fa[p]]=len[p],否则mi[p]=len[fa[p]]。(mi数组初始时为0)
这样可以在O(n)更新parent树.
然后再扫一遍节点,如果mi[p]<len[p],anslen=min(anslen,mi[p]+1),这样就得到了anslen。(anslen为最小串的长度)
在扫一遍节点把所有可行答案求个字典序最小的就行了。(这一步远远没有O(anslen*|p|),p是可行答案集合的大小,时间复杂度可以看下一个做法的时间)
2.网上看到的做法
把其他串建立广义sam,然后让第一个串在上面跑。
这样每当失配的时候,沿parent树走到符合条件的节点p,则此时最小可行字符串长度为len[fa[p]]+2,拿他去更新答案即可。
这做法时间复杂度更高,因为字符串比较次数比做法一多(它可能比较了长度大于anslen的字符串),且建立sam的时间复杂度也高。
贴个做法2的代码把,一的不想写了
#include <bits/stdc++.h> using namespace std; struct SAM { static const int MAXN = 1000001<<1;//大小为字符串长度两倍 static const int LetterSize = 26; int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN]; int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组 void init( void) { last = tot = 1; len[1] = 0; memset( ch[1], 0, sizeof ch[1]); } void add( int x) { int p = last, np = last = ++tot; len[np] = len[p]+ 1, cnt[last] = 1; memset( ch[np], 0, sizeof ch[np]); while( p && !ch[p][x]) ch[p][x] = np, p = fa[p]; if( p == 0) fa[np] = 1; else { int q = ch[p][x]; if( len[q] == len[p] + 1) fa[np] = q; else { int nq = ++tot; memcpy( ch[nq], ch[q], sizeof ch[q]); len[nq] = len[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 toposort( void) { for(int i = 1; i <= len[last]; i++) sum[i] = 0; for(int i = 1; i <= tot; i++) sum[len[i]]++; for(int i = 1; i <= len[last]; i++) sum[i] += sum[i-1]; for(int i = 1; i <= tot; i++) tp[sum[len[i]]--] = i; } void go(char *ss) { int mi=0x3f3f3f3f,l; for(int i=0,p=1,num=0,slen=strlen(ss);i<slen;i++) { int c=ss[i]-'a'; if(ch[p][c]) p=ch[p][c],num++; else { while(p&&!ch[p][c]) p=fa[p]; if(p) num=len[p]+1,p=ch[p][c]; else p=1,num=0; if(num+1<mi) mi=num+1,l=i-num; else if(num+1==mi) for(int j=l,k=i-num;k<=i;k++,j++) if(ss[j]!=ss[k]) { if(ss[j]>ss[k]) l=i-num; break; } } } if(mi==0x3f3f3f3f) printf("Impossible"); else for(int i=0;i<mi;i++) printf("%c",ss[i+l]); } } sam; char sa[1000000],sb[1000000]; int main(void) { int t,n,cs=1;cin>>t; while(t--) { sam.init(); scanf("%d%s",&n,sa); for(int i=1;i<n;i++) { scanf("%s",sb); for(char *p=sb;*p;p++) sam.add(*p-'a'); sam.last=1; } printf("Case #%d: ",cs++); sam.go(sa); printf("\n"); } return 0; }
- UVAL 7902 2016ECfinal F - Mr. Panda and Fantastic Beasts
- 2016 ACM-ICPC China Finals #F Mr. Panda and Fantastic Beasts
- Gym101194F-Mr. Panda and Fantastic Beasts
- 2016 China Final F Mr. Panda and Fantastic Beasts
- Mr. Panda and Crystal HDU - 6007 最短路+完全背包
- Mr. Panda and Crystal HDU - 6007
- HDU6007-Mr. Panda and Crystal
- [acm/icpc2016ChinaFinal][CodeforcesGym101194] Mr.Panda and TubeMaster
- Hdu 6007 Mr. Panda and Crystal 最短路+完全背包
- hdu 6007 Mr. Panda and Crystal(最短路+完全背包)
- Codeforces 101206 I & HDU 6007 Mr. Panda and Crystal
- HDU 6007 Mr. Panda and Crystal (最短路 + 完全背包)
- hdu6007 Mr. Panda and Crystal 最短路+完全背包
- HDU 6007 Mr. Panda and Crystal (背包+spfa)
- Gym101194C-Mr. Panda and Strips
- [费用流] ACM-ICPC Asia China-Final Contest J. Mr.Panda and TubeMaster
- Problem I. Mr. Panda and Crystal
- ECNU CCCC选拔赛 A题 Mr. Frog and big news 排序不等式
- Mr. Bender and Square
- 翻译:Panda3D Manual/V. Programming with Panda/I. Fog and Lighting