kuangbin带你飞 后缀数组 题解
2份模板 DC3 。 空间复杂度O3N 时间复杂度On
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
}
倍增 空间复杂度ON,时间复杂度ONLOGN
RMQ,LCP还有没测试过!
int sa[MAXN],r[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN]; void build_sa(int s[],int n,int m)
{
int i,j,p,*x = t1,*y = t2;
for(i = ; i < m ; i++) c[i] = ;
for(i = ; i < n ; i++) c[x[i] = s[i]]++;
for(i = ; i < m ; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(j = ; j <= n ; j <<= )
{
p=;
for(i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < m ; i++) c[i] = ;
for(i = ; i < n ; i++) c[x[y[i]]]++;
for(i = ; i < m ; i++) c[i]+=c[i-];
for(i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = ;
x[sa[]] = ;
for(i = ; i < n ; i++)
x[sa[i]] = y[sa[i - ]] == y[sa[i]] && y[sa[i - ] + j] == y[sa[i] + j] ? p - : p++;
if(p >= n)break;
m = p;
}
} void getHeight(int s[],int n)
{
int i,j,k = ;
for(i = ;i <= n ; i++) Rank[sa[i]] = i;
for(i = ;i < n ; i++)
{
if(k)k--;
j = sa[Rank[i] - ];
while(s[i + k] == s[j + k])k++;
height[Rank[i]] = k;
}
}
/*
int mm[MAXN];
int best[20][MAXN];
void initRMQ(int n)
{
mm[0] = -1;
for(int i = 1 ; i <= n ;i++)
mm[i] = ((i & (i - 1)) == 0)?mm[i - 1] + 1:mm[i - 1];
for(int i = 1 ; i <=n ; i++) best[0][i] = i;
for(int i = 1 ; i <=mm[n] ; i++)
for(int j = 1 ; j + (1 << i) - 1 <= n ; j++)
{
int a=best[i - 1][j];
int b=best[i - 1][j + (1 << (i - 1))];
if(height[a] < height[b]) best[i][j] = a;
else best[i][j] = b;
}
} int askRMQ(int a,int b)
{
int t;
t=mm[b - a + 1];
b -= (1 << t) - 1;
a = best[t][a];b = best[t][b];
return height[a]<height[b] ? a : b;
}
int lcp(int a,int b)
{
a = Rank[a];b = Rank[b];
if(a > b)swap(a,b);
return height[askRMQ(a + 1,b)];
}
*/
POJ 1743 Musical Theme
复制一波题意:
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。“主题”是整个音符序列的一个子串,它需要满足如下条件:
1.长度至少为5个音符。
2.在乐曲中重复出现。(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值)
3.重复出现的同一主题不能有公共部分。
首先构造差分序列,二分+height分段。至于不能重叠维护每一段最大值最小值。判断是否重叠即可
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXN][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
}
int num[MAXN];
int N; bool judge(int mid)
{
int MIN = INF,MAX = -;
int cas = ;
while (true)
{
while (cas <= N && height[cas] < mid) cas++;
if (cas > N) break;
MIN = sa[cas - ];
MAX = sa[cas - ];
while (cas <= N && height[cas] >= mid)
{
MIN = min(sa[cas],MIN);
MAX = max(sa[cas],MAX);
cas++;
}
if (MAX - MIN >= mid) return true;
}
return false;
} int main()
{
while (scanf("%d",&N) != EOF)
{
if (N == ) break;
for (int i = ; i < N ; i++)
scanf("%d",&num[i]);
if (N < )
{
puts("");
continue;
}
N--;
for (int i = ; i < N ; i++)
{
num[i] = num[i + ] - num[i] + ;
}
num[N] = ;
dc3(num,sa,N + ,);
calheight(num,sa,N);
// for (int i = 0 ; i < N ; i++)
// printf("%d ",height[i]); putchar('\n');
int L = ,R = N / + ;
int ans = -;
while (L <= R)
{
int mid = (L + R) / ;
if (judge(mid))
{
ans = mid;
L = mid + ;
}
else R = mid - ;
}
if (ans != -) printf("%d\n",ans + );
else puts("");
}
return ;
}
POJ 3261 Milk Patterns
可重叠至少出现K次最长子串
二分+height分段
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int N;
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int K;
int num[MAXN]; bool judge(int mid)
{
int cas = ,cnt = ;
while (true)
{
while (cas <= N && height[cas] < mid) cas++;
if (cas > N) break;
int cnt = ;
while (cas <= N && height[cas] >= mid)
{
cas++;
cnt++;
}
if (cnt >= K) return true;
}
return false;
} int main()
{
while (scanf("%d%d",&N,&K) != EOF)
{
for (int i = ; i < N ; i++)
scanf("%d",&num[i]);
for (int i = ; i < N ; i++)
num[i]++;
num[N] = ;
dc3(num,sa,N + ,);
calheight(num,sa,N);
int ans = -;
//for (int i = 0 ; i < N ; i++)
// printf("%d ",height[i]);putchar('\n');
int L = ,R = ;
while (L <= R)
{
int mid = (L + R) / ;
if (judge(mid))
{
L = mid + ;
ans = mid;
}
else R = mid - ;
}
printf("%d\n",ans);
}
return ;
}
SPOJ DISUBSTR DISUBSTR - Distinct Substrings
不重复的子串的个数
//所有子串都是某个后缀的前缀,那么对于每一个后缀,使他的起始位置为sa[i],那么它对答案的贡献是n - sa[i];
//然而还有重复的。这个sa[i]与sa[i - 1]的LCP是height[i],那么说明sa[i -1]也有对应height个后缀已经计入答案,
//所以实际对答案的贡献是N - sa[i] - height[i];
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int N;
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int num[MAXN];
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%s",str);
N = strlen(str);
for (int i = ; i < N ; i++) num[i] = str[i];
num[N] = ;
da(num,sa,N + ,);
calheight(num,sa,N);
// for (int i = 0 ; i <= N ; i++) printf("%d ",height[i]);puts("");
//for (int i = 1 ; i <= N ; i++) printf("%d ",sa[i]); putchar('\n');
int ret = ;
for (int i = ; i <= N ; i++) ret += N - sa[i] - height[i];
//所有子串都是某个后缀的前缀,那么对于每一个后缀,使他的起始位置为sa[i],那么它对答案的贡献是n - sa[i];
//然而还有重复的。这个sa[i]与sa[i - 1]的LCP是height[i],那么说明sa[i -1]也有对应height个后缀已经计入答案,
//所以实际对答案的贡献是N - sa[i] - height[i];
printf("%d\n",ret);
}
return ;
}
SPOJ SUBST1 SUBST1 - New Distinct Substrings
通上一题,只是变化了数据大小
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int N;
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int num[MAXN];
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%s",str);
N = strlen(str);
for (int i = ; i < N ; i++) num[i] = str[i];
num[N] = ;
da(num,sa,N + ,);
calheight(num,sa,N);
//for (int i = 1 ; i <= N ; i++) printf("%d ",height[i]);puts("");
//for (int i = 1 ; i <= N ; i++) printf("%d ",sa[i]); putchar('\n');
int ret = ;
for (int i = ; i <= N ; i++) ret += N - sa[i] - height[i];
//所有子串都是某个后缀的前缀,那么对于每一个后缀,使他的起始位置为sa[i],那么它对答案的贡献是n - sa[i];
//然而还有重复的。这个sa[i]与sa[i - 1]的LCP是height[i],那么说明sa[i -1]也有对应height个后缀已经计入答案,
//所以实际对答案的贡献是N - sa[i] - height[i];
printf("%d\n",ret);
}
return ;
}
POJ 2406 Power Strings
找最小循环节
KMP经典题,后缀数组我写额MLE了。。
KMP_AC
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define MAXN 3000010
int Next[MAXN],len;
char str[MAXN];
void kmp_pre()
{
int i, j;
j = Next[] = - ;
i = ;
while (i < len)
{
while (j != - && str[i] != str[j]) j = Next[j];
Next[++i] = ++j;
}
}
int main()
{
while (scanf("%s",str) != EOF)
{
if (str[] == '.') break;
len = strlen(str);
kmp_pre();
//for (int i = 0 ; i <= len ; i++) printf("next[%d] = %d\n",i,next[i]);
// putchar('\n');
if (len % (len - Next[len]) == ) printf("%d\n",len / (len - Next[len]) );
else printf("%d\n",); }
return ;
}
MLE 也存下。没想着要去压他
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN];
char str[MAXN];
int r[MAXN],sa[MAXN],N;
bool cmp(int *r,int a,int b,int l)
{
return r[a] == r[b] && r[a + ] == r[b + ];
} void da(int str[],int sa[],int Rank[],int height[],int n,int m)
{
int i,j,p,*x = t1,*y = t2;
for (int i = ; i < m ; i++) c[i] = ;
for (int i = ; i < n ; i++) c[x[i] = str[i]]++;
for (int i = ; i < m ; i++) c[i] += c[i - ];
for (int i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for (int j = ; j <= n ; j <<= )
{
p = ;
for (i = n - j ; i < n ; i++) y[p++] = i;
for (i = ; i < n ; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = ; i < m ; i++) c[i] = ;
for (i = ; i < n ; i++) c[x[y[i]]]++;
for (i = ; i < m ; i++) c[i] += c[i - ];
for (i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = ;
x[sa[]] = ;
for (i = ; i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
if (p >= n) break;
m = p;
}
n--;
int k = ;
for (i = ; i <= n ; i++) Rank[sa[i]] = i;
for (i = ; i < n ; i++)
{
if (k) k--;
j = sa[Rank[i] - ];
while (str[i + k] == str[j + k]) k++;
height[Rank[i]] = k;
}
} int RMQ[MAXN];
int mm[MAXN];
int best[][MAXN]; void initRMQ(int n)
{
mm[] = -;
for (int i = ; i <= n ; i++)
mm[i] = ((i & (i - )) == ) ? mm[i - ] + : mm[i - ];
for (int i = ; i <= n ; i++) best[][i] = i;
for (int i = ; i <= mm[n] ; i++)
for (int j = ; j + ( << i) - <= n ; j++)
{
int a = best[i - ][j];
int b = best[i - ][j + ( << (i - ))];
if (RMQ[a] < RMQ[b]) best[i][j] = a;
else best[i][j] = b;
}
} int askrmq(int a,int b)
{
int t;
t = mm[b - a + ];
b -= ( << t) - ;
a = best[t][a];
b = best[t][b];
return RMQ[a] < RMQ[b] ? a : b;
} int lcp(int a,int b)
{
a = Rank[a];
b = Rank[b];
if (a > b) swap(a,b);
return height[askrmq(a + ,b)];
} bool judge(int length)
{
if (N % length) return false;
int tmp = lcp(, + length);
// printf("%d %d \n",length,1 + length);
// printf("%d %d\n",length,tmp);
if (tmp == N - length) return true;
return false;
} int main()
{
while (scanf("%s",str) != EOF)
{
if (str[] == '.') break;
N = strlen(str);
for (int i = ; i < N ; i++) r[i] = str[i];
r[N] = ;
da(r,sa,Rank,height,N + ,);
initRMQ(N);
int ret = ;
for (int i = ; i <= N / + ; i++)
{
if(judge(i))
{
ret = N / i;
// printf("%d\n",i);
break;
}
}
printf("%d\n",ret);
}
return ;
}
SPOJ SPOJ REPEATS REPEATS - Repeats
论文里的题目:参照后缀数组处理字符串的有力工具。
论文里没提到的就是有一种情况下,可以由于不是整除的匹配可以在向左或向右是的重复次数再加1
算法分析:
先穷举长度 L,然后求长度为 L 的子串最多能连续出现几次。首先连续出现
1 次是肯定可以的,所以这里只考虑至少 2 次的情况。假设在原字符串中连续出
现 2 次,记这个子字符串为 S,那么 S 肯定包括了字符 r[0], r[L], r[L*2],
r[L*3], ……中的某相邻的两个。所以只须看字符 r[L*i]和 r[L*(i+1)]往前和
往后各能匹配到多远,记这个总长度为 K,那么这里连续出现了 K/L+1 次。最后
看最大值是多少。如图 7 所示。
穷举长度 L 的时间是 n,每次计算的时间是 n/L。所以整个做法的时间复杂
度是 O(n/1+n/2+n/3+……+n/n)=O(nlogn)。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int calcu(int n)
{
int ret = ;
for (int l = ; l < n ; l++)
{
for (int i = ; i + l < n ; i += l)
{
int length = rmq(i,i + l);
int tmp = length / l + ;
int left = i - (l - length % l);
if (left >= && length % l && rmq(left,left + l) >= length)
tmp++;
ret = max(ret,tmp);
}
}
return ret;
}
char input[];
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int N;
scanf("%d",&N);
for (int i = ; i < N ; i++)
{
scanf("%s",input);
r[i] = (int)input[] + ;
}
r[N] = ;
dc3(r,sa,N + ,);
calheight(r,sa,N);
RMQ_init(N,height);
printf("%d\n",calcu(N));
}
return ;
}
POJ 3693 Maximum repetition substring
通上一题
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int ans[MAXM],tot;
pair<int,int>output;
int calcu(int n)
{
int ret = ;
for (int l = ; l < n ; l++)
{
for (int i = ; i + l < n ; i += l)
{
int length = rmq(i,i + l);
int tmp = length / l + ;
int left = i - (l - length % l);
if (left >= && length % l && rmq(left,left + l) >= length)
tmp++;
if (tmp == ret)
{
ans[tot++] = l;
}
else if (tmp > ret)
{
tot = ;
ans[tot++] = l;
ret = tmp;
}
}
}
return ret;
} int main()
{
//freopen("sample.txt","r",stdin);
int kase = ,N;
while (scanf("%s",input) != EOF)
{
if (input[] == '#') break;
N = strlen(input);
for (int i = ; i < N ; i++)
r[i] = input[i];
r[N] = ;
dc3(r,sa,N + ,);
calheight(r,sa,N);
RMQ_init(N,height);
int maxcnt = calcu(N);
tot = unique(ans,ans + tot) - ans;
printf("Case %d: ",kase++);
bool flag = false;
for (int i = ; i <= N && !flag ; i++)
{
for (int j = ; j < tot ; j++)
{
int length = ans[j];
if (rmq(sa[i],sa[i] + length) >= (maxcnt - ) * length)
{
output.first = sa[i];
output.second = sa[i] + maxcnt * length - ;
flag = true;
}
}
}
for (int i = output.first ; i <= output.second ; i++)
printf("%c",input[i]);
putchar('\n');
}
return ;
}
POJ 2774 Long Long Message
2个串的最长公共子串
水体,拼串后缀数组直接做
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int posmid; int calcu(int N)
{
int ret = ;
for (int i = ; i <= N ; i++)
{
int l = sa[i - ],r = sa[i];
if (l > r) swap(l,r);
if (l <= posmid && r <= posmid) continue;
if (r >= posmid && l >= posmid) continue;
ret = max(ret,height[i]);
}
return ret;
}
int main()
{
int N,cas;
while (scanf("%s",str) != EOF)
{
cas = ;
int len = strlen(str);
for (int i = ; i < len ; i++)
r[cas++] = str[i];
posmid = cas;
r[cas++] = ;
scanf("%s",str);
len = strlen(str);
for (int i = ; i < len ; i++)
r[cas++] = str[i];
r[cas] = ;
// for (int i = 0 ; i <= cas ; i++)
// printf("%d ",r[i]); putchar('\n');
N = cas;
dc3(r,sa,N + ,);
calheight(r,sa,N);
printf("%d\n",calcu(N));
}
return ;
}
POJ 3415 Common Substrings
这个题也是论问题,很难。尤其是单调栈哪里
这里论文内容
给定两个字符串 A 和 B,求长度不小于 k 的公共子串的个数(可以相同)。
样例 1:
A=“xx”,B=“xx”,k=1,长度不小于 k 的公共子串的个数是 5。
样例 2:
A = “aababaa”,B = “abaabaa”,k=2,长度不小于 k 的公共子串的个数是22。
算法分析:
基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,
把最长公共前缀长度不小于 k 的部分全部加起来。先将两个字符串连起来,中间
用一个没有出现过的字符隔开。按 height 值分组后,接下来的工作便是快速的
统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个 B 的后缀就统
计与前面的 A 的后缀能产生多少个长度不小于 k 的公共子串,这里 A 的后缀需要
用一个单调的栈来高效的维护。然后对 A 也这样做一次。具体的细节留给读者思
考。
首先对于A,B串的2个后缀,他们对答案的贡献是LCP - K + 1,前提是LCP >= K;
如果你直接暴力那么复杂度就是N*N*LOGN;
所以要用单调栈优化。这里我一直想不出扎弄。看了别人的代码半天看懂了。
首先第一步是分布统计,第一次同意每一个B串前面A串与之的LCP额答案。第二次反过来。2次答案和就是我们要的
那么问题就是每一步的同意,维护一个变量tot这个就是对答案的影响
注意到2个串的LCP就是他们所在RANK之间的height 的最小值。仔细想一下。对于每一个B串,他与前面的A串与他之间的LCP是单调不减的。于是你
可以维护处这个单调递增额栈。里面是height值和这个height对后边几个穿的影响;这里说起来麻烦,举例子说也很麻烦。
大致距离一下有5个后缀,ABCDE,对应就是4个height值我认为他是h1,h2,h3,h4相应的就是A-B LCP,B-C LCP 。。。。
如果有H1 < H4 < H2 < H3 ,注意这里我不讨论那个后缀是A串后缀那个后缀是B串后缀了。虽然仍然很重要。
我们从左向右扫的时候有。H1,H2,H3一直单调递增很简单处理。到这里答案就是lcp(a,b) + lcp(c,a) + lcp(c,b) + lcp(d,a) + lcp(d,b) + lcp(d,c) = h1 + h1 + h1 + h2 + h2 + h3;
站内统计的就是他所"支配的"A串个数,遇到H4的时候就要有出栈,有了这个H4。之后所有的B串与C,D位置的LCP至少不会由H2,H3来管,可能与H4相关,我们把H2,H3出栈,H4入展
同事要维护tot,就是栈内所有元素的价值,这个不太好说明白。关键就是这个量。具体看代码把
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
int dp[MAXM][];
int N;
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} char input[MAXM];
int cas,K,posmid;
int Stack[MAXN][],top; int main()
{
while (scanf("%d",&K) != EOF)
{
if (K == ) break;
cas = ;
scanf("%s",input);
int len = strlen(input);
posmid = len;
for (int i = ; i < len ; i++)
r[cas++] = input[i];
r[cas++] = ;
scanf("%s",input);
len = strlen(input);
for (int i = ; i < len ; i++)
r[cas++] = input[i];
r[cas] = ;
N = cas;
// for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('\n');
LL ret = ,tot = ;
top = ;
dc3(r,sa,N + ,);
calheight(r,sa,N);
for (int i = ; i <= N ; i++)
{
if (height[i] < K)
{
tot = ;
top = ;
}
else
{
int num = ;
if (sa[i - ] < posmid)
{
num++;
tot += (LL)(height[i] - K + );
}
while (top > && height[i] <= Stack[top - ][])
{
top--;
tot -= (LL)Stack[top][] * (Stack[top][] - height[i]);
num += Stack[top][];
}
Stack[top][] = height[i];
Stack[top++][] = num;
if (sa[i] > posmid) ret += (LL)tot;
}
}
tot = ;
top = ;
for (int i = ; i <= N ; i++)
{
if (height[i] < K)
{
tot = ;
top = ;
}
else
{
int num = ;
if (sa[i - ] > posmid)
{
num++;
tot += (LL)(height[i] - K + );
}
while (top > && height[i] <= Stack[top - ][])
{
top--;
tot -= (LL)Stack[top][] * (Stack[top][] - height[i]);
num += Stack[top][];
}
Stack[top][] = height[i];
Stack[top++][] = num;
if (sa[i] < posmid) ret += (LL)tot;
}
}
printf("%I64d\n",ret);
}
return ;
}
POJ 3294 Life Forms
题意:求大于k/2个字符串中含有的最长公共子串
二分+height分段+判断
如何输出参照下代码吧
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[];
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int cas,N;
vector<int> ret,tmp;
int pos[],cnt,num;
int comp[MAXN],tot; bool judge(int mid)
{
int step = ;
tot = ;
while (true)
{
int cnt = ;
while (step <= N && height[step] < mid) step++;
if (step > N) break;
tot = ;
while (height[step] >= mid)
{
int lft = sa[step - ];
int rht = sa[step];
int poslft = lower_bound(pos,pos + num,lft) - pos;
int posrht = lower_bound(pos,pos + num,rht) - pos;
comp[tot++] = poslft;
comp[tot++] = posrht;
step++;
}
sort(comp,comp + tot);
tot = unique(comp,comp + tot) - comp;
if (tot % == && tot > num / )
return true;
else if (tot % == && tot >= (num + ) / )
return true;
}
return false;
} void output(int length)
{
int step = ;
while (true)
{
while (step <= N && height[step] < length) step++;
if (step > N) break;
tot = ;
int st = step;
while (step <= N && height[step] >= length)
{
int lft = sa[step - ];
int rht = sa[step];
int poslft = lower_bound(pos,pos + num,lft) - pos;
int posrht = lower_bound(pos,pos + num,rht) - pos;
comp[tot++] = poslft;
comp[tot++] = posrht;
step++;
}
sort(comp,comp + tot);
tot = unique(comp,comp + tot) - comp;
if ((tot % == && tot > num / ) || (tot % == && tot >= (num + ) / ))
{
int srt = sa[st - ];
for (int i = srt ,j = ; j < length ; j++,i++)
printf("%c",r[i] - );
putchar('\n');
}
}
} int main()
{
// freopen("sample.txt","r",stdin);
bool first = true;
while (scanf("%d",&num) != EOF)
{
if (num == ) break;
if (first) first = false;
else puts("");
cas = ;
int step = ;
int tmp = ;
for (int i = ; i < num ; i++)
{
scanf("%s",str);
int len = strlen(str);
tmp = max(len,tmp);
for (int j = ; j < len ; j++)
r[cas++] = str[j] + ;
pos[i] = cas;
r[cas++] = step;
step++;
}
cas--;
N = cas;
//for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('\n');
//for (int i = 0 ; i < num ; i++) printf("%d ",pos[i]); putchar('\n');
dc3(r,sa,N + ,);
calheight(r,sa,N);
int l = ,r = tmp,ans = ;
ret.clear();
while (l <= r)
{
int mid = (l + r) / ;
if (judge(mid))
{
l = mid + ;
ans = mid;
}
else r = mid - ;
}
// printf("%d\n",ans);
if (ans == ) puts("?");
else
output(ans);
}
return ;
}
SPOJ PHRASES PHRASES - Relevant Phrases of Annihilation
在每个串都至少出现2次
二分判断时每个分串计算最大最小位置值既可以了。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[];
int dp[MAXM][];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
} void RMQ_init(int n,int b[])
{
int i,j;
for(i = ; i <= n ; i++)
dp[i][] = b[i];
for(j = ; ( << j) <= n ; j++)
for(i = ; i + ( << j) - <= n ; i++)
dp[i][j] = min(dp[i][j - ],dp[i + (<<(j - ))][j - ]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + )*1.0)/log(2.0));
return min(dp[s][k],dp[v - ( << k) + ][k]);
} int cas,N,num;
int pos[];
int MIN[],MAX[]; bool judge(int mid)
{
int step = ;
while (true)
{
while (step <= N && height[step] < mid) step++;
if (step > N) break;
for (int i = ; i < ; i++)
{
MIN[i] = INF;
MAX[i] = -INF;
}
while (step <= N && height[step] >= mid)
{
int lft = sa[step - ];
int rht = sa[step];
int poslft = lower_bound(pos,pos + num,lft) - pos;
int posrht = lower_bound(pos,pos + num,rht) - pos;
MIN[poslft] = min(MIN[poslft],lft);
MAX[poslft] = max(MAX[poslft],lft);
MIN[posrht] = min(MIN[posrht],rht);
MAX[posrht] = max(MAX[posrht],rht);
step++;
}
bool flag = false;
for (int i = ; i < num ; i++)
{
//printf("%d %d\n",MIN[i],MAX[i]);
if (MIN[i] == INF || MAX[i] == -INF || MAX[i] <= MIN[i] + mid - )
{
flag = true;
break;
}
}
// putchar('\n');
if (!flag) return true;
}
return false;
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&num);
cas = ;
int step = ;
for (int i = ; i < num ; i++)
{
scanf("%s",str);
int len = strlen(str);
for (int j = ; j < len ; j++)
r[cas++] = str[j] + ;
pos[i] = cas;
r[cas++] = step++;
}
cas--;
N = cas;
dc3(r,sa,N + ,);
calheight(r,sa,N);
// for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('\n');
// for (int i = 0 ; i < num ; i++) printf("%d ",pos[i]); putchar('\n');
int L = ,R = ,ans = ;
while (L <= R)
{
int mid = (L + R) / ;
if (judge(mid))
{
L = mid + ;
ans = mid;
}
else R = mid - ;
}
//printf("%d\n",judge(2));
printf("%d\n",ans);
}
return ;
}
POJ 1226 substrings
题意:给定n个串,求一个最大子串长度,使得它或者它的逆向串在每个串中出现
每个串正向逆向构造出来然后所有串拼到一起 。其他的大致一样
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[],res[];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
sort(r + ,wa,wb,tbc,m);
sort(r + ,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
}
/*
void RMQ_init(int n,int b[])
{
int i,j;
for(i = 1 ; i <= n ; i++)
dp[i][0] = b[i];
for(j = 1 ; (1 << j) <= n ; j++)
for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
} int rmq(int s,int v)
{
s = Rank[s],v = Rank[v];
if(s > v)swap(s,v);
s++;
int k=(int)(log((v - s + 1)*1.0)/log(2.0));
return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}
*/ int cas,N,num;
int belong[];
bool vis[]; bool judge(int mid)
{
int step = ;
while(true)
{
while (step <= N && height[step] < mid) step++;
if (step > N) break;
memset(vis,false,sizeof(vis));
while (step <= N && height[step] >= mid)
{
vis[belong[sa[step - ]]] = true;
vis[belong[sa[step]]] = true;
step++;
}
bool found = true;
for (int i = ; i < num ; i++)
{
if (!vis[i])
{
found = false;
break;
}
}
if (found) return true;
}
return false;
} int main()
{
// freopen("sample.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&num);
cas = ;
int step = ;
for (int i = ; i < num ; i++)
{
scanf("%s",str);
int len = strlen(str);
for (int j = ; j < len ; j++)
{
belong[cas] = i;
if (islower(str[j]))
{
r[cas++] = str[j] - 'a' + ;
}
else r[cas++] = str[j] - 'A' + ;
}
belong[cas] = -;
r[cas++] = step++;
for (int k = , j = len - ; j >= ; k++,j--)
res[k] = str[j];
res[len] = '\0';
for (int j = ; j < len ; j++)
{
belong[cas] = i;
if (islower(res[j])) r[cas++] = res[j] - 'a' + ;
else r[cas++] = res[j] - 'A' + ;
}
belong[cas] = -;
r[cas++] = step++;
}
cas--;
N = cas;
// for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('\n');
// for (int i = 0 ; i <= N ; i++) printf("%d ",belong[i]); putchar('\n');
dc3(r,sa,N + ,);
calheight(r,sa,N);
int L = ,R = ;
int ans = ;
while (L <= R)
{
int mid = (L + R) / ;
if (judge(mid))
{
ans = mid;
L = mid + ;
}
else R = mid - ;
}
printf("%d\n",ans);
}
return ;
}
UVA 11475 Extend to Palindrome
在末尾添加最少的字符使得串回文。
将串反过来。
以反串为模式串,原本串有主串,KMP找最大匹配长度。其他的补足输出就可
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
char str[MAXN],rev[MAXN];
int fail[MAXN]; void kmp_pre(char x[],int m,int fail[])
{
int i,j;
j = fail[] = -;
i = ;
while (i < m)
{
while (j != - && x[i] != x[j]) j = fail[j];
fail[++i] = ++j;
}
} int kmp_find(char x[],int m,char y[],int n)
{
int i,j;
i = j = ;
while(i < n)
{
while (j != - && y[i] != x[j]) j = fail[j];
i++;
j++;
if (j >= m) return j;
}
return j;
} int main()
{
while (scanf("%s",str) != EOF)
{
int len = strlen(str);
for (int j = len - , i = ; i < len ; j--,i++)
rev[i] = str[j];
rev[len] = '\0';
// printf("%s\n%s\n",str,rev);
kmp_pre(rev,len,fail);
int pos = kmp_find(rev,len,str,len);
printf("%s%s\n",str,rev + pos);
}
return ;
}
POJ 3581 Sequence
http://blog.163.com/just_gogo/blog/static/1914390652011823103842787/
将原本的串分成三段,每段反过来厚字典序最小。参照了别人的。真心蠢啊。
解题思路:
其实这个思路是在discuss里面看到的;用的后缀数组。。
原理很简单:把数子按逆序求一次后缀数组(sa数组),然后里面最小的那个就可以直接输出了(当然为了满足分成3份,所以最小的那个sa[min]要>=2这里是从0开始的);
然后将剩下的数字复制一遍贴在剩下的数字后面(可能有点拗口,比如剩下的数字为:3 2 4那么复制一下在贴在 后面就成了3 2 4 3 2 4);
然后再对这个求一次后缀数组;这样就可以输出了最小(sa[min]>0)的那一串数字了。。再最后就输出剩下的那些数字了;
刚开始的时候觉得没有必要将剩下的数字复制一片贴在剩下的数字后面,所以wa了很多次。。。
最后在discuss里面看见一组数据:
9
8 4 -1 5 0 5 0 2 3
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5(开始的时候我并没有复制一遍) 对应输出:0 5
第三步
3 2 0 5 对应输出: 3 2 0 5
可以看见这样做是不对的。。
必须要将剩下的字符串复制一遍贴在后面,然后再来求后缀数组。。。
正解:
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5 3 2 0 5 0 5 对应输出: 0 5 0 5;
第三步
3 2 对应输出:3 2;
最后值得注意的是此题还要用离散化。。因为并没有告诉我们输入的数据有多大。。。。。
代码
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = ;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int c0(int *r,int a,int b)
{return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ];}
int c12(int k,int *r,int a,int b)
{if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(,r,a + ,b + );
else return r[a] < r[b] || r[a] == r[b] && wv[a + ]< wv[b + ];}
void Sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n ; i++) wv[i] = r[a[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) b[--wsd[wv[i]]] = a[i];
} void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn = r + n ,*san = sa + n,ta = ,tb = (n + ) / ,tbc = ,p;
r[n] = r[n + ] = ;
for(i = ; i < n ; i++) if(i % != ) wa[tbc++] = i;
Sort(r + ,wa,wb,tbc,m);
Sort(r + ,wb,wa,tbc,m);
Sort(r,wa,wb,tbc,m);
for(p = ,rn[F(wb[])] = ,i = ; i < tbc ; i++)
rn[F(wb[i])] = c0(r,wb[i - ],wb[i])?p - : p++;
if(p < tbc) dc3(rn,san,tbc,p);
else for(i = ; i < tbc ; i++) san[rn[i]] = i;
for(i = ;i < tbc ; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ;
Sort(r,wb,wa,ta,m);
for(i = ; i < tbc ; i++) wv[wb[i] = G(san[i])] = i;
for(i = ,j = ,p = ; i < ta && j < tbc ; p++)
sa[p]=c12(wb[j] % ,r,wa[i],wb[j]) ? wa[i++] : wb[j++];
for(;i < ta ; p++) sa[p] = wa[i++];
for(;j < tbc ; p++) sa[p] = wb[j++];
} int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x = wa,*y = wb,*t;
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[x[i] = r[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[x[i]]] = i;
for(j = , p = ; p < n ; j *= ,m = p)
{
for(p = ,i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n ; i++) wv[i] = x[y[i]];
for(i = ; i < m ; i++) wsd[i] = ;
for(i = ; i < n ; i++) wsd[wv[i]]++;
for(i = ; i < m ; i++) wsd[i] += wsd[i - ];
for(i = n - ; i >= ; i--) sa[--wsd[wv[i]]] = y[i];
for(t = x,x = y,y = t,p = ,x[sa[]] = ,i = ;i < n ; i++)
x[sa[i]] = cmp(y,sa[i - ],sa[i],j) ? p - : p++;
}
} int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
int i,j,k = ;
for(i = ; i <= n ; i++) Rank[sa[i]] = i;
for(i = ; i < n ; height[Rank[i++]] = k)
for(k ? k--:,j = sa[Rank[i] - ] ;r[i + k]==r[j + k];k++);
}
/*
int RMQ[MAXN];
int mm[MAXN];
int best[20][MAXN]; void initRMQ(int n)
{
mm[0] = -1;
for (int i = 1 ; i <= n ; i++)
mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
for (int i = 1 ; i <= n ; i++) best[0][i] = i;
for (int i = 1 ; i <= mm[n] ; i++)
for (int j = 1 ; j + (1 << i) - 1 <= n ; j++)
{
int a = best[i - 1][j];
int b = best[i - 1][j + (1 << (i - 1))];
if (RMQ[a] < RMQ[b]) best[i][j] = a;
else best[i][j] = b;
}
} int askrmq(int a,int b)
{
int t;
t = mm[b - a + 1];
b -= (1 << t) - 1;
a = best[t][a];
b = best[t][b];
return RMQ[a] < RMQ[b] ? a : b;
} int lcp(int a,int b)
{
a = Rank[a];
b = Rank[b];
if (a > b) swap(a,b);
return height[askRMQ(a + 1,b)];
}
*/ struct node
{
int val;
int newval;
int id;
friend bool operator < (const node &a,const node &b)
{ return a.val < b.val;
}
}src[MAXN];
int N; int cmp1(const node &a,const node &b)
{
return a.id > b.id;
} int main()
{
scanf("%d",&N);
for (int i = ; i < N ; i++)
{
scanf("%d",&src[i].val);
src[i].id = i + ;
}
sort(src,src + N);
src[].newval = ;
for (int i = ; i < N ; i++)
{
if (src[i].val == src[i - ].val)
src[i].newval = src[i - ].newval;
else src[i].newval = src[i - ].newval + ;
}
sort(src,src + N,cmp1);
for (int i = ; i < N ; i++)
r[i] = src[i].newval;
r[N] = ;
dc3(r,sa,N + ,N + );
int i;
for(i = ; i <= N && sa[i] <= ; i++);
int pos1 = sa[i];
for (i = pos1 ; i < N ; i++) printf("%d\n",src[i].val);
for (i = ; i < pos1 ; i++) src[i + pos1] = src[i];
//for (i = 0 ; i < 2 * pos1 ; i++) printf("%d ",src[i].val); putchar('\n');
for (i = ; i < * pos1 ; i++) r[i] = src[i].newval;
N = * pos1;
r[N] = ;
dc3(r,sa,N + ,N + );
int pos2;
for (i = ; i <= N && (!sa[i] || sa[i] >= N / ) ; i++);
pos2 = sa[i];
for (i = pos2 ; i < N / ; i++) printf("%d\n",src[i].val);
for (i = ; i < pos2 ; i++) printf("%d\n",src[i].val);
return ;
}
POJ 3450 Corporate Identity
每个串都有的最长的最小字典序的串
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
int sa[MAXN],r[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN]; void build_sa(int s[],int n,int m)
{
int i,j,p,*x = t1,*y = t2;
for(i = ; i < m ; i++) c[i] = ;
for(i = ; i < n ; i++) c[x[i] = s[i]]++;
for(i = ; i < m ; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(j = ; j <= n ; j <<= )
{
p=;
for(i = n - j ; i < n ; i++) y[p++] = i;
for(i = ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < m ; i++) c[i] = ;
for(i = ; i < n ; i++) c[x[y[i]]]++;
for(i = ; i < m ; i++) c[i]+=c[i-];
for(i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = ;
x[sa[]] = ;
for(i = ; i < n ; i++)
x[sa[i]] = y[sa[i - ]] == y[sa[i]] && y[sa[i - ] + j] == y[sa[i] + j] ? p - : p++;
if(p >= n)break;
m = p;
}
} void getHeight(int s[],int n)
{
int i,j,k = ;
for(i = ;i <= n ; i++) Rank[sa[i]] = i;
for(i = ;i < n ; i++)
{
if(k)k--;
j = sa[Rank[i] - ];
while(s[i + k] == s[j + k])k++;
height[Rank[i]] = k;
}
}
/*
int mm[MAXN];
int best[20][MAXN];
void initRMQ(int n)
{
mm[0] = -1;
for(int i = 1 ; i <= n ;i++)
mm[i] = ((i & (i - 1)) == 0)?mm[i - 1] + 1:mm[i - 1];
for(int i = 1 ; i <=n ; i++) best[0][i] = i;
for(int i = 1 ; i <=mm[n] ; i++)
for(int j = 1 ; j + (1 << i) - 1 <= n ; j++)
{
int a=best[i - 1][j];
int b=best[i - 1][j + (1 << (i - 1))];
if(height[a] < height[b]) best[i][j] = a;
else best[i][j] = b;
}
} int askRMQ(int a,int b)
{
int t;
t=mm[b - a + 1];
b -= (1 << t) - 1;
a = best[t][a];b = best[t][b];
return height[a]<height[b] ? a : b;
}
int lcp(int a,int b)
{
a = Rank[a];b = Rank[b];
if(a > b)swap(a,b);
return height[askRMQ(a + 1,b)];
}
*/ int num;
int N,cas;
bool vis[];
char str[];
int belong[MAXN];
int ans[MAXN],tot; bool judge(int mid)
{
int step = ;
while (true)
{
while (step <= N && height[step] < mid) step++;
if (step > N) break;
memset(vis,false,sizeof(vis));
while (step <= N && height[step] >= mid)
{
int lft = belong[sa[step - ]];
int rht = belong[sa[step]];
vis[lft] = vis[rht] = true;
step++;
}
bool flag = false;
for (int i = ; i < num ; i++)
{
if (!vis[i])
{
flag = true;
break;
}
}
if (!flag) return true;
}
return false;
} int ret;
void output(int length)
{
ret = INF;
int step = ;
while (true)
{
while (step <= N && height[step] < length) step++;
if (step > N) break;
int Min = sa[step - ];
memset(vis,false,sizeof(vis));
while (step <= N && height[step] >= length)
{
int lft = belong[sa[step - ]];
int rht = belong[sa[step]];
vis[lft] = vis[rht] = true;
step++;
}
bool flag = false;
for (int i = ; i < num ; i++)
{
if (!vis[i])
{
flag = true;
break;
}
}
if (!flag)
{
ret = Min;
break;
}
}
for (int i = ,j = ret ; i < length ; i++,j++)
printf("%c",r[j] - );
putchar('\n');
} int main()
{
while (scanf("%d",&num) != EOF)
{
if (num == ) break;
cas = ;
int step = ;
for (int i = ; i < num ; i++)
{
scanf("%s",str);
int len = strlen(str);
for (int j = ; j < len ; j++)
{
belong[cas] = i;
r[cas++] = str[j] + ;
}
belong[cas] = -;
r[cas++] = step;
step++;
}
cas--;
N = cas; build_sa(r,N + ,);
getHeight(r,N);
// for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); puts("");
int ans = ,L = ,R = ;
while (L <= R)
{
int mid = (L + R) / ;
if (judge(mid))
{
ans = mid;
L = mid + ;
}
else R = mid -;
}
// printf("%d\n",ans);
if (ans == ) puts("IDENTITY LOST");
else
{
output(ans);
}
}
return ;
}
POJ 3080 Blue Jeans
数据太小了。直接KMP爆。直接裸爆都行
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXN = ;
char str[MAXN],src[MAXN];
int fail[MAXN];
struct node
{
char word[];
int length;
friend bool operator < (const node &a,const node &b)
{
return a.length < b.length;
}
}res[MAXN]; void kmp_pre(char x[],int m,int fail[])
{
int i,j;
j = fail[] = -;
i = ;
while (i < m)
{
while (j != - && x[i] != x[j]) j = fail[j];
fail[++i] = ++j;
}
} bool kmp_find(char x[],int m,char y[],int n)
{
int i,j;
i = j = ;
while(i < n)
{
while (j != - && y[i] != x[j]) j = fail[j];
i++;
j++;
if (j >= m) return true;
}
return false;
} int main()
{
//freopen("sample.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--)
{
int N;
scanf("%d",&N);
for (int i = ; i < N ; i++)
{
scanf("%s",res[i].word);
res[i].length = strlen(res[i].word);
}
sort(res,res + N);
char tmp[],cmp[];
int ret = ;
for (int l = ; l < res[].length ; l++)
{
for (int r = l ; r < res[].length ; r++)
{
int leap = ;
for (int i = l ; i <= r ; i++)
tmp[leap++] = res[].word[i];
tmp[leap] = '\0';
bool flag = false;
kmp_pre(tmp,leap,fail);
for (int i = ; i < N ; i++)
{
if (!kmp_find(tmp,leap,res[i].word,res[i].length))
{
flag = true;
break;
}
}
if (!flag)
{
if (r - l + > ret)
{
ret = r - l + ;
int step = ;
for (int i = l ; i <= r ; i++)
cmp[step++] = res[].word[i];
cmp[step] = '\0';
}
else if (r - l + == ret)
{
if (strcmp(tmp,cmp) < ) strcpy(cmp,tmp);
}
}
}
}
if (ret < ) printf("no significant commonalities\n");
else
{
printf("%s\n",cmp);
}
}
return ;
}
POJ 2758 Checking the Text
我看HUST没人做。就不做了。汗!!
记到这里一旦哪天想做了呢
kuangbin带你飞 后缀数组 题解的更多相关文章
- kuangbin带你飞 最短路 题解
求一个图最短路边的办法.好像下面的那个有问题.单向边和双向边一定是有区别的.这个比较容易.参照该文的最短路网络流题目和连通图题目一题求最短路关节边 另外上述2个题目的代码好像有问题. 在UVALIVE ...
- Kuangbin 带你飞 数位DP题解
以前一直不知道该咋搞这个比较好. 感觉推起来那个数字好麻烦.后来有一种比较好的写法就是直接的DFS写法.相应的ismax表示当前位是否有限制. 数位DP也是有一种类似模版的东西,不过需要好好理解.与其 ...
- Dancing Links [Kuangbin带你飞] 模版及题解
学习资料: http://www.cnblogs.com/grenet/p/3145800.html http://blog.csdn.net/mu399/article/details/762786 ...
- 「kuangbin带你飞」专题十八 后缀数组
layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...
- 「kuangbin带你飞」专题十七 AC自动机
layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...
- KUANGBIN带你飞
KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题 //201 ...
- [kuangbin带你飞]专题1-23题目清单总结
[kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...
- Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目
Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是 ...
- 「kuangbin带你飞」专题二十 斜率DP
layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...
随机推荐
- sphinx调用API参考(官方手册)
API的参考实现是用PHP写成的,因为(我们相信)较之其他语言,Sphinx在PHP中应用最广泛.因此这份参考文档基于PHP API的参考,而且这节中的所有的代码样例都用PHP给出. 当然,其他所有A ...
- 关于缺失值(missing value)的处理---机器学习 Imputer
关于缺失值(missing value)的处理 在sklearn的preprocessing包中包含了对数据集中缺失值的处理,主要是应用Imputer类进行处理. 首先需要说明的是,numpy的数组中 ...
- 【iOS开发】initWithNibName、initWithCoder、awakeFromNib和 loadNibNamed详解
第一.initWithNibName这个方法是在controller的类在IB中创建,但是通过Xcode实例化controller的时候用的. 第二.initWithCoder 是一个类在IB中创建但 ...
- 算法(2) Find All Numbers Disappeared in an Array
题目:整数数组满足1<=a[i]<=n(n是数组的长度),某些元素出现一次,某些元素出现两次,在数组a[i]中找到[1,n]区间中未出现的数字.比如输入[4,3,2,7,8,2,3,1], ...
- Dubbo 项目与传统项目
1.什么是传统工程 单工程 MVC 架构 控制层通过调用服务层完成业务逻辑处理 业务层调用持久层进程数据操作 2.什么是分布式工程 将传统项目的单工程结构,拆分成多工程 一般会有这几个工程: 父工程: ...
- jQuery插件jquery.fullPage.js
简介如今我们经常能看到全屏网站,尤其是国外网站.这些网站用几幅很大的图片或者色块做背景,再添加一些简单的内容,显得格外的高端大气上档次,比如 iPone 5C 的介绍页面.QQ浏览器的官方网站.百度史 ...
- [CF327E]Axis Walking([洛谷P2396]yyy loves Maths VII)
题目大意:给一个长度为$n(1\leqslant n\leqslant24)$的序列$S$和$k(0\leqslant k\leqslant2)$个数. 求有多少种$S$的排列方式使得其任何一个前缀和 ...
- [洛谷P1407][国家集训队]稳定婚姻
题目大意:有$n$对夫妻和$m$对情人,如果一对情人中的两人都离婚了,那么他们可以结为夫妻.对于每一对夫妻,若他们离婚后所有人依然可以结婚,那么就是不安全的,否则是安全的.问每一对夫妻是否安全. 题解 ...
- 【BZOJ】2453: 维护队列【BZOJ】2120: 数颜色 二分+分块(暴力能A)
先说正解:把所有相同的数相成一个链在每一个区间里的种数就是不同链的链头,那么记录每个数的上个相同数所在位置,那么只要找出l到r之间前驱值在l之前的数的个数就可以了 本人打的暴力,有一个小技巧,用cha ...
- bzoj4145 AMPPZ2014 The Prices 状压dp
这个题.......很可以,很小清晰......反正正经的东西我都没想到:重点在于——————我不会处理那个多出来的路费所以当时我就骚骚的弄了一颗树包状压其实这是一个类01背包的状压在每个状态用01背 ...