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带你飞 后缀数组 题解的更多相关文章

  1. kuangbin带你飞 最短路 题解

    求一个图最短路边的办法.好像下面的那个有问题.单向边和双向边一定是有区别的.这个比较容易.参照该文的最短路网络流题目和连通图题目一题求最短路关节边 另外上述2个题目的代码好像有问题. 在UVALIVE ...

  2. Kuangbin 带你飞 数位DP题解

    以前一直不知道该咋搞这个比较好. 感觉推起来那个数字好麻烦.后来有一种比较好的写法就是直接的DFS写法.相应的ismax表示当前位是否有限制. 数位DP也是有一种类似模版的东西,不过需要好好理解.与其 ...

  3. Dancing Links [Kuangbin带你飞] 模版及题解

    学习资料: http://www.cnblogs.com/grenet/p/3145800.html http://blog.csdn.net/mu399/article/details/762786 ...

  4. 「kuangbin带你飞」专题十八 后缀数组

    layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...

  5. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  6. KUANGBIN带你飞

    KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题    //201 ...

  7. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  8. Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目

    Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是 ...

  9. 「kuangbin带你飞」专题二十 斜率DP

    layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...

随机推荐

  1. 第二篇 Fiddler配置_浏览器&手机

    什么是Fiddler? 网络项目的开发和测试中,Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的 ,可以说是非常常用的手头工具了,本文就Fiddler使用和配置进行说明. ...

  2. 修改有数据oracle字段类型 从number转为varchar

    --修改有数据oracle字段类型 从number转为varchar--例:修改ta_sp_org_invoice表中RESCUE_PHONE字段类型,从number转为varchar --step1 ...

  3. 目标检测之Faster-RCNN的pytorch代码详解(模型准备篇)

    十月一的假期转眼就结束了,这个假期带女朋友到处玩了玩,虽然经济仿佛要陷入危机,不过没关系,要是吃不上饭就看书,吃精神粮食也不错,哈哈!开个玩笑,是要收收心好好干活了,继续写Faster-RCNN的代码 ...

  4. c#执行插入sql 时,报错:异常信息:超时时间已到。在操作完成之前超时时间已过或服务器未响应

    问题:c#执行插入sql 时,报错:异常信息:超时时间已到.在操作完成之前超时时间已过或服务器未响应 解决: SqlCommand cmd = new SqlCommand(); cmd.Comman ...

  5. 官方文档 恢复备份指南七 Using Flashback Database and Restore Points

    本章内容: Understanding Flashback Database, Restore Points and Guaranteed Restore Points Logging for Fla ...

  6. # ML学习小笔记—Gradien Descent

    关于本课程的相关资料http://speech.ee.ntu.edu.tw/~tlkagk/courses_ML17.html 根据前面所为,当我们得到Loss方程的时候,我们希望求得最优的Loss方 ...

  7. EXEL文件转成简书MD表格

    EXEL文件转成简书MD表格 0.1.3 mac: https://github.com/fanfeilong/exceltk/blob/master/pub/exceltk.0.1.3.pkg wi ...

  8. Oracle锁表查询以及解锁

    一.查看锁表进程SQL语句 select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo ...

  9. [剑指Offer] 16.合并两个排序链表

    题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. [思路1]递归 /* struct ListNode { int val; struct Lis ...

  10. 使用XML传递数据

    HTML <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...